00001 #include "slate.hpp"
00002
00003 static const char* opcode_names[] = {
00004 "direct send message ",
00005 "indirect send message ",
00006 "-",
00007 "load literal ",
00008 "store literal ",
00009 "send message with opts ",
00010 "-",
00011 "new closure ",
00012 "new array with ",
00013 "resend message ",
00014 "return from ",
00015 "load env ",
00016 "load var ",
00017 "store var ",
00018 "load free var ",
00019 "store free var ",
00020 "is identical to ",
00021 "branch keyed ",
00022 "jump to ",
00023 "move reg ",
00024 "branch true ",
00025 "branch false ",
00026 "return reg ",
00027 "return val ",
00028 "resume ",
00029 "primitiveDo ",
00030 "directApplyTo ",
00031 "is nil ",
00032 "inline primitive check jump ",
00033 "inline method check jump "
00034 };
00035
00036 void print_opcode_args(struct object_heap* oh, std::vector<struct Object*>& code, size_t start, size_t args) {
00037 for (size_t i = start; i < start+args; i++) {
00038 print_type(oh, code[i]);
00039 }
00040 }
00041
00042
00043
00044 void print_code(struct object_heap* oh, std::vector<struct Object*> code) {
00045
00046 for (size_t i = 0; i < code.size(); i += opcode_length(code, i)) {
00047 printf("[%" PRIuMAX "] ", i);
00048 word_t rawop = (word_t)code[i];
00049 if (rawop >= OP_INTERNAL_SEND) {
00050 printf("<internal>");
00051 } else {
00052 printf("%s", opcode_names[rawop>>1]);
00053 }
00054 print_opcode_args(oh, code, i+1, opcode_length(code, i)-1);
00055 printf("\n");
00056 }
00057
00058
00059 }
00060
00061 word_t opcode_length(std::vector<struct Object*>& code, word_t start){
00062 return 1 + opcode_base_length((word_t)code[start]) + opcode_arg_length(code, start);
00063 }
00064
00065
00066 word_t opcode_arg_length(std::vector<struct Object*>& code, word_t start) {
00067 word_t op = (word_t)code[start];
00068 word_t i = start+1;
00069 switch (op) {
00070 case OP_SEND: case OP_INTERNAL_SEND: return object_to_smallint(code[i+2]);
00071 case OP_SEND_MESSAGE_WITH_OPTS: return object_to_smallint(code[i+2]);
00072 case OP_NEW_ARRAY_WITH: return object_to_smallint(code[i+1]);
00073 case OP_PRIMITIVE_DO: return object_to_smallint(code[i+1]);
00074 case OP_APPLY_TO: return object_to_smallint(code[i+1]);
00075 case OP_INLINE_PRIMITIVE_CHECK: return object_to_smallint(code[i+3]);
00076 case OP_INLINE_METHOD_CHECK: return object_to_smallint(code[i+1]);
00077
00078
00079 case OP_LOAD_LITERAL:
00080 case OP_NEW_CLOSURE:
00081 case OP_RESEND_MESSAGE:
00082 case OP_RETURN_FROM:
00083 case OP_LOAD_ENVIRONMENT:
00084 case OP_LOAD_VARIABLE:
00085 case OP_STORE_VARIABLE:
00086 case OP_LOAD_FREE_VARIABLE:
00087 case OP_STORE_FREE_VARIABLE:
00088 case OP_IS_IDENTICAL_TO:
00089 case OP_BRANCH_KEYED:
00090 case OP_JUMP_TO:
00091 case OP_MOVE_REGISTER:
00092 case OP_BRANCH_IF_TRUE:
00093 case OP_BRANCH_IF_FALSE:
00094 case OP_RETURN_REGISTER:
00095 case OP_RETURN_VALUE:
00096 case OP_RESUME:
00097 case OP_IS_NIL:
00098 return 0;
00099
00100
00101 default: assert(0);
00102 }
00103 return 0;
00104 }
00105
00106
00107 word_t opcode_base_length(word_t rawop) {
00108 switch (rawop) {
00109 case OP_SEND: case OP_INTERNAL_SEND: return 3;
00110 case OP_LOAD_LITERAL: return 2;
00111 case OP_SEND_MESSAGE_WITH_OPTS: return 4;
00112 case OP_NEW_CLOSURE: return 2;
00113 case OP_NEW_ARRAY_WITH: return 2;
00114 case OP_RESEND_MESSAGE: return 2;
00115 case OP_RETURN_FROM: return 2;
00116 case OP_LOAD_ENVIRONMENT: return 1;
00117 case OP_LOAD_VARIABLE: return 1;
00118 case OP_STORE_VARIABLE: return 1;
00119 case OP_LOAD_FREE_VARIABLE: return 3;
00120 case OP_STORE_FREE_VARIABLE: return 3;
00121 case OP_IS_IDENTICAL_TO: return 3;
00122 case OP_BRANCH_KEYED: return 2;
00123 case OP_JUMP_TO: return 1;
00124 case OP_MOVE_REGISTER: return 2;
00125 case OP_BRANCH_IF_TRUE: return 2;
00126 case OP_BRANCH_IF_FALSE: return 2;
00127 case OP_RETURN_REGISTER: return 1;
00128 case OP_RETURN_VALUE: return 1;
00129 case OP_RESUME: return 0;
00130 case OP_PRIMITIVE_DO: return 3;
00131 case OP_APPLY_TO: return 3;
00132 case OP_IS_NIL: return 2;
00133 case OP_INLINE_PRIMITIVE_CHECK: return 5;
00134 case OP_INLINE_METHOD_CHECK: return 3;
00135 default: assert(0);
00136 }
00137 return 0;
00138
00139 }
00140
00141
00142 word_t opcode_jump_offset(word_t rawop) {
00143 switch (rawop) {
00144 case OP_JUMP_TO: return 1;
00145 case OP_BRANCH_IF_FALSE: return 2;
00146 case OP_BRANCH_IF_TRUE: return 2;
00147 case OP_INLINE_PRIMITIVE_CHECK: return 5;
00148 case OP_INLINE_METHOD_CHECK: return 3;
00149 default: assert(0);
00150 }
00151 return 0;
00152 }
00153
00154
00155 word_t opcode_jump_adjustment(word_t rawop) {
00156 switch (rawop) {
00157 case OP_JUMP_TO: return -1;
00158 case OP_BRANCH_IF_FALSE: return -1;
00159 case OP_BRANCH_IF_TRUE: return -1;
00160 case OP_INLINE_PRIMITIVE_CHECK: return 0;
00161 case OP_INLINE_METHOD_CHECK: return 0;
00162 default: assert(0);
00163 }
00164 return 0;
00165 }
00166
00167 bool opcode_can_jump(word_t rawop) {
00168 switch (rawop) {
00169 case OP_JUMP_TO:
00170 case OP_BRANCH_IF_FALSE:
00171 case OP_BRANCH_IF_TRUE:
00172 case OP_INLINE_PRIMITIVE_CHECK:
00173 case OP_INLINE_METHOD_CHECK:
00174 return true;
00175 default:
00176
00177 assert(opcode_base_length(rawop) >= 0);
00178 return false;
00179
00180 }
00181 return 0;
00182 }
00183
00184
00185
00186
00187 word_t opcode_register_locations(word_t rawop) {
00188 switch (rawop) {
00189 case OP_SEND: case OP_INTERNAL_SEND: return 1;
00190 case OP_LOAD_LITERAL: return 1;
00191 case OP_SEND_MESSAGE_WITH_OPTS: return 1+8;
00192 case OP_NEW_CLOSURE: return 1;
00193 case OP_NEW_ARRAY_WITH: return 1;
00194
00195 case OP_RESEND_MESSAGE: return 1;
00196 case OP_RETURN_FROM: return 1;
00197 case OP_LOAD_ENVIRONMENT: return 1;
00198 case OP_LOAD_VARIABLE: return 1;
00199 case OP_STORE_VARIABLE: return 1;
00200 case OP_LOAD_FREE_VARIABLE: return 1;
00201 case OP_STORE_FREE_VARIABLE: return 4;
00202 case OP_IS_IDENTICAL_TO: return 1+2+4;
00203 case OP_BRANCH_KEYED: return 1+2;
00204 case OP_JUMP_TO: return 0;
00205 case OP_MOVE_REGISTER: return 1+2;
00206 case OP_BRANCH_IF_TRUE: return 1;
00207 case OP_BRANCH_IF_FALSE: return 1;
00208 case OP_RETURN_REGISTER: return 1;
00209 case OP_RETURN_VALUE: return 0;
00210 case OP_RESUME: return 0;
00211 case OP_PRIMITIVE_DO: return 1+4;
00212 case OP_APPLY_TO: return 1+4;
00213 case OP_IS_NIL: return 1+2;
00214 case OP_INLINE_PRIMITIVE_CHECK: return 1;
00215 case OP_INLINE_METHOD_CHECK: return 0;
00216 default: assert(0);
00217 }
00218
00219 return 0;
00220 }
00221
00222 void optimizer_append_code_to_vector(struct OopArray* code, std::vector<struct Object*>& vector) {
00223 std::copy(code->elements, code->elements + array_size(code), std::back_inserter(vector));
00224
00225 }
00226
00227 void optimizer_offset_value(std::vector<struct Object*>& code, word_t pos, word_t offset) {
00228 struct Object* obj = code[pos];
00229 assert(object_is_smallint(obj));
00230 code[pos] = smallint_to_object(object_to_smallint(obj) + offset);
00231 }
00232
00233 void optimizer_offset_registers(std::vector<struct Object*>& code, int offset) {
00234 word_t offsets, opcodeArgCount, baseLength;
00235 for (size_t i = 0; i < code.size(); i += opcode_length(code, i)) {
00236 offsets = opcode_register_locations((word_t)code[i]);
00237 baseLength = opcode_base_length((word_t)code[i]);
00238 opcodeArgCount = opcode_arg_length(code, i);
00239
00240
00241 assert (offsets < 16);
00242 for (word_t offsetBit = 0; offsetBit < 6; offsetBit++) {
00243 word_t offsetMask = 1 << offsetBit;
00244 if ((offsets & offsetMask) == offsetMask) {
00245 optimizer_offset_value(code, i + 1 + offsetBit, offset);
00246 }
00247 }
00248
00249
00250 for (size_t offsetArg = i + 1 + baseLength; offsetArg < i + 1 + baseLength + opcodeArgCount; offsetArg++) {
00251 optimizer_offset_value(code, offsetArg, offset);
00252 }
00253
00254 }
00255
00256 }
00257
00258
00259 void optimizer_insert_code(std::vector<struct Object*>& code, size_t offset, std::vector<struct Object*>& newCode) {
00260 assert(offset >= 0 && offset <= code.size());
00261
00262
00263
00264
00265 for (size_t i = 0; i < offset; i += opcode_length(code, i)) {
00266 if (opcode_can_jump((word_t)code[i])) {
00267 word_t codeJumpParameter = opcode_jump_offset((word_t)code[i]);
00268 word_t jumpOffset = object_to_smallint(code[i + codeJumpParameter]);
00269 jumpOffset += opcode_jump_adjustment((word_t)code[i]);
00270 if (i + opcode_length(code, i) + jumpOffset > offset) {
00271 optimizer_offset_value(code, i + codeJumpParameter, newCode.size());
00272 }
00273 }
00274
00275 }
00276
00277
00278 for (size_t i = offset; i < code.size(); i += opcode_length(code, i)) {
00279 if (opcode_can_jump((word_t)code[i])) {
00280 word_t codeJumpParameter = opcode_jump_offset((word_t)code[i]);
00281 word_t jumpOffset = object_to_smallint(code[i + codeJumpParameter]);
00282 jumpOffset += opcode_jump_adjustment((word_t)code[i]);
00283 if (i + opcode_length(code, i) + jumpOffset < offset) {
00284 optimizer_offset_value(code, i + codeJumpParameter, 0 - newCode.size());
00285 }
00286 }
00287
00288 }
00289
00290 code.insert(code.begin() + offset, newCode.begin(), newCode.end());
00291
00292 }
00293
00294
00295 void optimizer_delete_code(std::vector<struct Object*>& code, size_t offset, word_t amount) {
00296 assert(offset >= 0 && offset < code.size() && amount > 0);
00297
00298
00299
00300
00301 for (size_t i = 0; i < offset; i += opcode_length(code, i)) {
00302 if (opcode_can_jump((word_t)code[i])) {
00303 word_t codeJumpParameter = opcode_jump_offset((word_t)code[i]);
00304 word_t jumpOffset = object_to_smallint(code[i + codeJumpParameter]);
00305 jumpOffset += opcode_jump_adjustment((word_t)code[i]);
00306 if (i + opcode_length(code, i) + jumpOffset > offset) {
00307 optimizer_offset_value(code, i + codeJumpParameter, 0 - amount);
00308 }
00309 }
00310
00311 }
00312
00313
00314 for (size_t i = offset; i < code.size(); i += opcode_length(code, i)) {
00315 if (opcode_can_jump((word_t)code[i])) {
00316 word_t codeJumpParameter = opcode_jump_offset((word_t)code[i]);
00317 word_t jumpOffset = object_to_smallint(code[i + codeJumpParameter]);
00318 jumpOffset += opcode_jump_adjustment((word_t)code[i]);
00319 if (i + opcode_length(code, i) + jumpOffset <= offset) {
00320 optimizer_offset_value(code, i + codeJumpParameter, amount);
00321 }
00322 }
00323
00324 }
00325
00326
00327 code.erase(code.begin() + offset, code.begin() + offset + amount);
00328 }
00329
00330
00331 bool optimizer_picEntry_compare(struct Object** entryA, struct Object** entryB) {
00332 return (word_t)entryA[PIC_CALLEE_COUNT] > (word_t)entryB[PIC_CALLEE_COUNT];
00333 }
00334
00335
00336 bool optimizer_method_can_be_optimized(struct object_heap* oh, struct CompiledMethod* method) {
00337 if (method->heapAllocate == oh->cached.true_object) return false;
00338 if (method->restVariable == oh->cached.true_object) return false;
00339 struct Object* traitsWindow = method->base.map->delegates->elements[0];
00340 if (traitsWindow == oh->cached.primitive_method_window) return false;
00341 std::vector<struct Object*> code;
00342 optimizer_append_code_to_vector(method->code, code);
00343 if (code.size() > INLINER_MAX_METHOD_SIZE) return false;
00344
00345 for (size_t i = 0; i < (size_t)array_size(method->code); i += opcode_length(code, i)) {
00346 switch ((word_t)code[i]) {
00347 case OP_BRANCH_KEYED:
00348 return false;
00349
00350 default: break;
00351 }
00352 }
00353
00354 return true;
00355 }
00356
00357
00358 bool optimizer_method_can_be_inlined(struct object_heap* oh, struct CompiledMethod* method) {
00359 if (method->heapAllocate == oh->cached.true_object) return false;
00360 if (method->restVariable == oh->cached.true_object) return false;
00361 struct Object* traitsWindow = method->base.map->delegates->elements[0];
00362 if (traitsWindow == oh->cached.primitive_method_window) return true;
00363
00364 if (array_size(method->optionalKeywords) != 0) return false;
00365 std::vector<struct Object*> code;
00366 optimizer_append_code_to_vector(method->code, code);
00367 if (code.size() > INLINER_MAX_INLINE_SIZE) return false;
00368
00369 for (size_t i = 0; i < (size_t)array_size(method->code); i += opcode_length(code, i)) {
00370 switch ((word_t)code[i]) {
00371 case OP_RESEND_MESSAGE:
00372 case OP_RESUME:
00373 case OP_RETURN_FROM:
00374 case OP_BRANCH_KEYED:
00375 case OP_STORE_FREE_VARIABLE:
00376 case OP_LOAD_FREE_VARIABLE:
00377
00378 return false;
00379
00380 default: break;
00381 }
00382 }
00383
00384 return true;
00385 }
00386
00387
00388 void optimizer_commonly_called_implementations(struct object_heap* oh, struct CompiledMethod* method, struct Symbol* selector, std::vector<struct Object**>& out) {
00389
00390 if ((struct Object*)method->calleeCount == oh->cached.nil) return;
00391 std::vector<struct Object**> picEntries;
00392 for (word_t i = 0; i < array_size(method->calleeCount); i += CALLER_PIC_ENTRY_SIZE) {
00393 struct MethodDefinition* def = (struct MethodDefinition*)method->calleeCount->elements[i+PIC_CALLEE];
00394 if ((struct Object*)def == oh->cached.nil) continue;
00395 struct CompiledMethod* picMethod = (struct CompiledMethod*)def->method;
00396 struct Object* traitsWindow = picMethod->base.map->delegates->elements[0];
00397 assert (traitsWindow == oh->cached.compiled_method_window || traitsWindow == oh->cached.primitive_method_window);
00398 struct Symbol* picSelector = picMethod->selector;
00399 if (selector != picSelector) continue;
00400 struct Object** picEntry = &method->calleeCount->elements[i];
00401 picEntries.push_back(picEntry);
00402 }
00403 if (picEntries.empty()) return;
00404 std::sort(picEntries.begin(), picEntries.end(), optimizer_picEntry_compare);
00405 for (size_t i = 0; i < picEntries.size(); i++) {
00406 struct CompiledMethod* method = (struct CompiledMethod*) ((struct MethodDefinition*)(picEntries[i])[PIC_CALLEE])->method;
00407 if (optimizer_method_can_be_inlined(oh, method)) {
00408 out.push_back(picEntries[i]);
00409 }
00410 }
00411 }
00412
00413 void optimizer_change_returns_to_jumps(struct object_heap* oh, std::vector<struct Object*>& code, word_t resultReg, word_t jumpOutDistance) {
00414
00415
00416 for (size_t i = 0; i < code.size(); i += opcode_length(code, i)) {
00417 if (OP_RETURN_REGISTER == (word_t)code[i]) {
00418 struct Object* reg = code[i+1];
00419 std::vector<struct Object*> codeToInsert;
00420 codeToInsert.push_back((struct Object*)OP_MOVE_REGISTER);
00421 codeToInsert.push_back(smallint_to_object(resultReg));
00422 codeToInsert.push_back(reg);
00423 codeToInsert.push_back((struct Object*)OP_JUMP_TO);
00424 codeToInsert.push_back(smallint_to_object(code.size() - i - 2 + jumpOutDistance + 1 ));
00425 optimizer_delete_code(code, i, 2);
00426 optimizer_insert_code(code, i, codeToInsert);
00427 } else if (OP_RETURN_VALUE == (word_t)code[i]) {
00428 struct Object* literal = code[i+1];
00429 std::vector<struct Object*> codeToInsert;
00430 codeToInsert.push_back((struct Object*)OP_LOAD_LITERAL);
00431 codeToInsert.push_back(smallint_to_object(resultReg));
00432 codeToInsert.push_back(literal);
00433 codeToInsert.push_back((struct Object*)OP_JUMP_TO);
00434 codeToInsert.push_back(smallint_to_object(code.size() - i - 2 + jumpOutDistance + 1));
00435 optimizer_delete_code(code, i, 2);
00436 optimizer_insert_code(code, i, codeToInsert);
00437
00438 }
00439 }
00440
00441
00442 }
00443
00444
00445 void optimizer_remove_redundant_ops(struct object_heap* oh, struct CompiledMethod* method, std::vector<struct Object*>& code) {
00446
00447 if (method->heapAllocate == oh->cached.true_object) return;
00448
00449 for (size_t i = 0; i < code.size(); ) {
00450 if (OP_LOAD_VARIABLE == (word_t)code[i]) {
00451 optimizer_delete_code(code, i, 2);
00452 } else if (OP_STORE_VARIABLE == (word_t)code[i]) {
00453 optimizer_delete_code(code, i, 2);
00454 } else {
00455 i += opcode_length(code, i);
00456 }
00457
00458 }
00459 }
00460
00461 void optimizer_remove_internal_ops(struct object_heap* oh, struct CompiledMethod* method, std::vector<struct Object*>& code) {
00462 for (size_t i = 0; i < code.size(); i += opcode_length(code, i)) {
00463 if (OP_INTERNAL_SEND >= (word_t)code[i]) {
00464 switch ((word_t)code[i]) {
00465 case OP_INTERNAL_SEND: code[i] = (struct Object*) OP_SEND; break;
00466 default: break;
00467 }
00468 }
00469 }
00470 }
00471
00472
00473
00474 size_t optimizer_op_location_before(std::vector<struct Object*>& code, size_t opPos) {
00475 size_t j = 0;
00476 for (size_t i = 0; i < code.size() && i != opPos; j = i, i += opcode_length(code, i));
00477 return j;
00478 }
00479
00480
00481
00482
00483 void optimizer_inline_callees(struct object_heap* oh, struct CompiledMethod* method) {
00484 std::vector<struct Object*> code;
00485 optimizer_append_code_to_vector(method->code, code);
00486 std::vector<struct Object**> commonCalledImplementations;
00487 word_t newRegisterCount = object_to_smallint(method->registerCount);
00488
00489
00490 for (size_t i = 0; i < code.size(); i += opcode_length(code, i)) {
00491
00492
00493
00494
00495 if (OP_INLINE_PRIMITIVE_CHECK == (word_t)code[i]) {
00496
00497 word_t jumpAmount = object_to_smallint(code[i + opcode_jump_offset((word_t)code[i])] + opcode_jump_adjustment((word_t)code[i]));
00498 size_t j = i + opcode_length(code, i);
00499 j += jumpAmount;
00500 size_t plainSendLocation = optimizer_op_location_before(code, j);
00501 assert(plainSendLocation < j
00502 && (OP_SEND == (word_t)code[plainSendLocation] || OP_INTERNAL_SEND == (word_t)code[plainSendLocation]));
00503
00504 if (OP_SEND == (word_t)code[plainSendLocation]) {
00505 code[plainSendLocation] = (struct Object*) OP_INTERNAL_SEND;
00506 }
00507 }
00508
00509
00510
00511 if (OP_INLINE_METHOD_CHECK == (word_t)code[i]) {
00512 word_t jumpAmount = object_to_smallint(code[i + opcode_jump_offset((word_t)code[i])] + opcode_jump_adjustment((word_t)code[i]));
00513 size_t j = i + opcode_length(code, i);
00514 j += jumpAmount;
00515 if (OP_SEND == (word_t)code[j]) {
00516 code[j] = (struct Object*) OP_INTERNAL_SEND;
00517 }
00518
00519 }
00520
00521
00522 if (OP_SEND != (word_t)code[i]) {
00523 continue;
00524 }
00525
00526
00527 code[i] = (struct Object*) OP_INTERNAL_SEND;
00528
00529 word_t resultReg = object_to_smallint(code[i+1]);
00530 struct Symbol* selector = (struct Symbol*)code[i+2];
00531 word_t arity = object_to_smallint(code[i+3]);
00532 commonCalledImplementations.clear();
00533
00534 optimizer_commonly_called_implementations(oh, method, selector, commonCalledImplementations);
00535
00536 for (size_t k = 0; k < commonCalledImplementations.size(); k++) {
00537 if (k > 2) break;
00538 struct Object** picEntry = commonCalledImplementations[k];
00539 struct MethodDefinition* def = (struct MethodDefinition*)picEntry[PIC_CALLEE];
00540 struct Object* traitsWindow = def->method->map->delegates->elements[0];
00541 if (traitsWindow == oh->cached.compiled_method_window) {
00542 struct CompiledMethod* cmethod = (struct CompiledMethod*)def->method;
00543 std::vector<struct Object*> inlineOpcodeCode, codeToInsert, preludeMoveRegisters;
00544 word_t requiredRegisters = object_to_smallint(cmethod->registerCount);
00545
00546 inlineOpcodeCode.push_back((struct Object*)OP_INLINE_METHOD_CHECK);
00547 inlineOpcodeCode.push_back(picEntry[PIC_CALLEE_MAPS]);
00548 inlineOpcodeCode.push_back(smallint_to_object(arity));
00549
00550 inlineOpcodeCode.push_back(smallint_to_object(opcode_length(code, i)));
00551 for (word_t g = 0; g < arity; g++) {
00552 inlineOpcodeCode.push_back(code[i + OP_SEND_PARAMETER_0 + g]);
00553 preludeMoveRegisters.push_back((struct Object*)OP_MOVE_REGISTER);
00554 preludeMoveRegisters.push_back(smallint_to_object(g + newRegisterCount));
00555 preludeMoveRegisters.push_back(code[i + OP_SEND_PARAMETER_0 + g]);
00556 }
00557
00558
00559 if ((struct Object*)cmethod->oldCode != oh->cached.nil) {
00560 optimizer_append_code_to_vector(cmethod->oldCode, codeToInsert);
00561 } else {
00562 optimizer_append_code_to_vector(cmethod->code, codeToInsert);
00563 }
00564
00565
00566
00567 optimizer_offset_registers(codeToInsert, newRegisterCount);
00568 newRegisterCount += requiredRegisters;
00569
00570 optimizer_remove_redundant_ops(oh, cmethod, codeToInsert);
00571
00572
00573 optimizer_insert_code(codeToInsert, 0, preludeMoveRegisters);
00574
00575
00576
00577 optimizer_change_returns_to_jumps(oh, codeToInsert, resultReg, opcode_length(code, i));
00578 inlineOpcodeCode[3] = smallint_to_object(codeToInsert.size());
00579 std::copy(codeToInsert.begin(), codeToInsert.end(), std::back_inserter(inlineOpcodeCode));
00580 optimizer_insert_code(code, i, inlineOpcodeCode);
00581
00582
00583
00584
00585
00586 i += inlineOpcodeCode.size();
00587
00588 } else if (traitsWindow == oh->cached.primitive_method_window) {
00589 struct PrimitiveMethod* pmethod = (struct PrimitiveMethod*)def->method;
00590 std::vector<struct Object*> codeToInsert;
00591 codeToInsert.push_back((struct Object*)OP_INLINE_PRIMITIVE_CHECK);
00592 codeToInsert.push_back(smallint_to_object(resultReg));
00593 codeToInsert.push_back(picEntry[PIC_CALLEE_MAPS]);
00594 codeToInsert.push_back(pmethod->index);
00595 codeToInsert.push_back(smallint_to_object(arity));
00596
00597 codeToInsert.push_back(smallint_to_object(opcode_length(code, i)));
00598 for (word_t g = 0; g < arity; g++) {
00599 codeToInsert.push_back(code[i + OP_SEND_PARAMETER_0 + g]);
00600 }
00601 optimizer_insert_code(code, i, codeToInsert);
00602
00603 i += codeToInsert.size();
00604 } else {
00605 assert(0);
00606 }
00607 }
00608
00609 }
00610
00611 optimizer_remove_redundant_ops(oh, method, code);
00612 optimizer_remove_internal_ops(oh, method, code);
00613
00614 struct OopArray* newCode = heap_clone_oop_array_sized(oh, get_special(oh, SPECIAL_OOP_ARRAY_PROTO), code.size());
00615 for (size_t i = 0; i < code.size(); i++) {
00616 newCode->elements[i] = code[i];
00617 }
00618 method->code = newCode;
00619 method->registerCount = smallint_to_object(newRegisterCount);
00620 heap_store_into(oh, (struct Object*) method, (struct Object*) method->code);
00621
00622
00623
00624 }