OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
300 if (value == 1) return i; | 300 if (value == 1) return i; |
301 } | 301 } |
302 } | 302 } |
303 UNREACHABLE(); | 303 UNREACHABLE(); |
304 return -1; | 304 return -1; |
305 } | 305 } |
306 | 306 |
307 | 307 |
308 void Deoptimizer::DoComputeOsrOutputFrame() { | 308 void Deoptimizer::DoComputeOsrOutputFrame() { |
309 DeoptimizationInputData* data = DeoptimizationInputData::cast( | 309 DeoptimizationInputData* data = DeoptimizationInputData::cast( |
310 optimized_code_->deoptimization_data()); | 310 compiled_code_->deoptimization_data()); |
311 unsigned ast_id = data->OsrAstId()->value(); | 311 unsigned ast_id = data->OsrAstId()->value(); |
312 // TODO(kasperl): This should not be the bailout_id_. It should be | 312 // TODO(kasperl): This should not be the bailout_id_. It should be |
313 // the ast id. Confusing. | 313 // the ast id. Confusing. |
314 ASSERT(bailout_id_ == ast_id); | 314 ASSERT(bailout_id_ == ast_id); |
315 | 315 |
316 int bailout_id = LookupBailoutId(data, BailoutId(ast_id)); | 316 int bailout_id = LookupBailoutId(data, BailoutId(ast_id)); |
317 unsigned translation_index = data->TranslationIndex(bailout_id)->value(); | 317 unsigned translation_index = data->TranslationIndex(bailout_id)->value(); |
318 ByteArray* translations = data->TranslationByteArray(); | 318 ByteArray* translations = data->TranslationByteArray(); |
319 | 319 |
320 TranslationIterator iterator(translations, translation_index); | 320 TranslationIterator iterator(translations, translation_index); |
(...skipping 16 matching lines...) Expand all Loading... |
337 USE(closure_id); | 337 USE(closure_id); |
338 ASSERT_EQ(Translation::kSelfLiteralId, closure_id); | 338 ASSERT_EQ(Translation::kSelfLiteralId, closure_id); |
339 unsigned height = iterator.Next(); | 339 unsigned height = iterator.Next(); |
340 unsigned height_in_bytes = height * kPointerSize; | 340 unsigned height_in_bytes = height * kPointerSize; |
341 USE(height_in_bytes); | 341 USE(height_in_bytes); |
342 | 342 |
343 unsigned fixed_size = ComputeFixedSize(function_); | 343 unsigned fixed_size = ComputeFixedSize(function_); |
344 unsigned input_frame_size = input_->GetFrameSize(); | 344 unsigned input_frame_size = input_->GetFrameSize(); |
345 ASSERT(fixed_size + height_in_bytes == input_frame_size); | 345 ASSERT(fixed_size + height_in_bytes == input_frame_size); |
346 | 346 |
347 unsigned stack_slot_size = optimized_code_->stack_slots() * kPointerSize; | 347 unsigned stack_slot_size = compiled_code_->stack_slots() * kPointerSize; |
348 unsigned outgoing_height = data->ArgumentsStackHeight(bailout_id)->value(); | 348 unsigned outgoing_height = data->ArgumentsStackHeight(bailout_id)->value(); |
349 unsigned outgoing_size = outgoing_height * kPointerSize; | 349 unsigned outgoing_size = outgoing_height * kPointerSize; |
350 unsigned output_frame_size = fixed_size + stack_slot_size + outgoing_size; | 350 unsigned output_frame_size = fixed_size + stack_slot_size + outgoing_size; |
351 ASSERT(outgoing_size == 0); // OSR does not happen in the middle of a call. | 351 ASSERT(outgoing_size == 0); // OSR does not happen in the middle of a call. |
352 | 352 |
353 if (FLAG_trace_osr) { | 353 if (FLAG_trace_osr) { |
354 PrintF("[on-stack replacement: begin 0x%08" V8PRIxPTR " ", | 354 PrintF("[on-stack replacement: begin 0x%08" V8PRIxPTR " ", |
355 reinterpret_cast<intptr_t>(function_)); | 355 reinterpret_cast<intptr_t>(function_)); |
356 function_->PrintName(); | 356 function_->PrintName(); |
357 PrintF(" => node=%u, frame=%d->%d, ebp:esp=0x%08x:0x%08x]\n", | 357 PrintF(" => node=%u, frame=%d->%d, ebp:esp=0x%08x:0x%08x]\n", |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
448 delete output_[0]; | 448 delete output_[0]; |
449 output_[0] = input_; | 449 output_[0] = input_; |
450 output_[0]->SetPc(reinterpret_cast<uint32_t>(from_)); | 450 output_[0]->SetPc(reinterpret_cast<uint32_t>(from_)); |
451 } else { | 451 } else { |
452 // Set up the frame pointer and the context pointer. | 452 // Set up the frame pointer and the context pointer. |
453 output_[0]->SetRegister(ebp.code(), frame_pointer); | 453 output_[0]->SetRegister(ebp.code(), frame_pointer); |
454 output_[0]->SetRegister(esi.code(), input_->GetRegister(esi.code())); | 454 output_[0]->SetRegister(esi.code(), input_->GetRegister(esi.code())); |
455 | 455 |
456 unsigned pc_offset = data->OsrPcOffset()->value(); | 456 unsigned pc_offset = data->OsrPcOffset()->value(); |
457 uint32_t pc = reinterpret_cast<uint32_t>( | 457 uint32_t pc = reinterpret_cast<uint32_t>( |
458 optimized_code_->entry() + pc_offset); | 458 compiled_code_->entry() + pc_offset); |
459 output_[0]->SetPc(pc); | 459 output_[0]->SetPc(pc); |
460 } | 460 } |
461 Code* continuation = | 461 Code* continuation = |
462 function_->GetIsolate()->builtins()->builtin(Builtins::kNotifyOSR); | 462 function_->GetIsolate()->builtins()->builtin(Builtins::kNotifyOSR); |
463 output_[0]->SetContinuation( | 463 output_[0]->SetContinuation( |
464 reinterpret_cast<uint32_t>(continuation->entry())); | 464 reinterpret_cast<uint32_t>(continuation->entry())); |
465 | 465 |
466 if (FLAG_trace_osr) { | 466 if (FLAG_trace_osr) { |
467 PrintF("[on-stack replacement translation %s: 0x%08" V8PRIxPTR " ", | 467 PrintF("[on-stack replacement translation %s: 0x%08" V8PRIxPTR " ", |
468 ok ? "finished" : "aborted", | 468 ok ? "finished" : "aborted", |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
562 Builtins* builtins = isolate_->builtins(); | 562 Builtins* builtins = isolate_->builtins(); |
563 Code* adaptor_trampoline = | 563 Code* adaptor_trampoline = |
564 builtins->builtin(Builtins::kArgumentsAdaptorTrampoline); | 564 builtins->builtin(Builtins::kArgumentsAdaptorTrampoline); |
565 uint32_t pc = reinterpret_cast<uint32_t>( | 565 uint32_t pc = reinterpret_cast<uint32_t>( |
566 adaptor_trampoline->instruction_start() + | 566 adaptor_trampoline->instruction_start() + |
567 isolate_->heap()->arguments_adaptor_deopt_pc_offset()->value()); | 567 isolate_->heap()->arguments_adaptor_deopt_pc_offset()->value()); |
568 output_frame->SetPc(pc); | 568 output_frame->SetPc(pc); |
569 } | 569 } |
570 | 570 |
571 | 571 |
| 572 void Deoptimizer::DoCompiledStubFrame(TranslationIterator* iterator, |
| 573 int frame_index) { |
| 574 // |
| 575 // FROM TO <-ebp |
| 576 // | .... | | .... | |
| 577 // +-------------------------+ +-------------------------+ |
| 578 // | JSFunction continuation | | JSFunction continuation | |
| 579 // +-------------------------+ +-------------------------+<-esp |
| 580 // | | saved frame (ebp) | |
| 581 // | +=========================+<-ebp |
| 582 // | | JSFunction context | |
| 583 // v +-------------------------+ |
| 584 // | COMPILED_STUB marker | ebp = saved frame |
| 585 // +-------------------------+ esi = JSFunction context |
| 586 // | | |
| 587 // | ... | |
| 588 // | | |
| 589 // +-------------------------+<-esp |
| 590 // |
| 591 // |
| 592 int output_frame_size = 1 * kPointerSize; |
| 593 FrameDescription* output_frame = |
| 594 new(output_frame_size) FrameDescription(output_frame_size, 0); |
| 595 Code* notify_miss = |
| 596 isolate_->builtins()->builtin(Builtins::kNotifyICMiss); |
| 597 output_frame->SetState(Smi::FromInt(FullCodeGenerator::NO_REGISTERS)); |
| 598 output_frame->SetContinuation( |
| 599 reinterpret_cast<uint32_t>(notify_miss->entry())); |
| 600 |
| 601 ASSERT(compiled_code_->kind() == Code::COMPILED_STUB); |
| 602 int major_key = compiled_code_->major_key(); |
| 603 CodeStubInterfaceDescriptor* descriptor = |
| 604 isolate_->code_stub_interface_descriptors()[major_key]; |
| 605 Handle<Code> miss_ic(descriptor->deoptimization_handler); |
| 606 output_frame->SetPc(reinterpret_cast<intptr_t>(miss_ic->instruction_start())); |
| 607 unsigned input_frame_size = input_->GetFrameSize(); |
| 608 intptr_t value = input_->GetFrameSlot(input_frame_size - kPointerSize); |
| 609 output_frame->SetFrameSlot(0, value); |
| 610 value = input_->GetFrameSlot(input_frame_size - 2 * kPointerSize); |
| 611 output_frame->SetRegister(ebp.code(), value); |
| 612 output_frame->SetFp(value); |
| 613 value = input_->GetFrameSlot(input_frame_size - 3 * kPointerSize); |
| 614 output_frame->SetRegister(esi.code(), value); |
| 615 |
| 616 Translation::Opcode opcode = |
| 617 static_cast<Translation::Opcode>(iterator->Next()); |
| 618 ASSERT(opcode == Translation::REGISTER); |
| 619 USE(opcode); |
| 620 int input_reg = iterator->Next(); |
| 621 intptr_t input_value = input_->GetRegister(input_reg); |
| 622 output_frame->SetRegister(edx.code(), input_value); |
| 623 |
| 624 int32_t next = iterator->Next(); |
| 625 opcode = static_cast<Translation::Opcode>(next); |
| 626 ASSERT(opcode == Translation::REGISTER); |
| 627 input_reg = iterator->Next(); |
| 628 input_value = input_->GetRegister(input_reg); |
| 629 output_frame->SetRegister(ecx.code(), input_value); |
| 630 |
| 631 ASSERT(frame_index == 0); |
| 632 output_[frame_index] = output_frame; |
| 633 } |
| 634 |
| 635 |
572 void Deoptimizer::DoComputeConstructStubFrame(TranslationIterator* iterator, | 636 void Deoptimizer::DoComputeConstructStubFrame(TranslationIterator* iterator, |
573 int frame_index) { | 637 int frame_index) { |
574 Builtins* builtins = isolate_->builtins(); | 638 Builtins* builtins = isolate_->builtins(); |
575 Code* construct_stub = builtins->builtin(Builtins::kJSConstructStubGeneric); | 639 Code* construct_stub = builtins->builtin(Builtins::kJSConstructStubGeneric); |
576 JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next())); | 640 JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next())); |
577 unsigned height = iterator->Next(); | 641 unsigned height = iterator->Next(); |
578 unsigned height_in_bytes = height * kPointerSize; | 642 unsigned height_in_bytes = height * kPointerSize; |
579 if (FLAG_trace_deopt) { | 643 if (FLAG_trace_deopt) { |
580 PrintF(" translating construct stub => height=%d\n", height_in_bytes); | 644 PrintF(" translating construct stub => height=%d\n", height_in_bytes); |
581 } | 645 } |
(...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
990 void Deoptimizer::FillInputFrame(Address tos, JavaScriptFrame* frame) { | 1054 void Deoptimizer::FillInputFrame(Address tos, JavaScriptFrame* frame) { |
991 // Set the register values. The values are not important as there are no | 1055 // Set the register values. The values are not important as there are no |
992 // callee saved registers in JavaScript frames, so all registers are | 1056 // callee saved registers in JavaScript frames, so all registers are |
993 // spilled. Registers ebp and esp are set to the correct values though. | 1057 // spilled. Registers ebp and esp are set to the correct values though. |
994 | 1058 |
995 for (int i = 0; i < Register::kNumRegisters; i++) { | 1059 for (int i = 0; i < Register::kNumRegisters; i++) { |
996 input_->SetRegister(i, i * 4); | 1060 input_->SetRegister(i, i * 4); |
997 } | 1061 } |
998 input_->SetRegister(esp.code(), reinterpret_cast<intptr_t>(frame->sp())); | 1062 input_->SetRegister(esp.code(), reinterpret_cast<intptr_t>(frame->sp())); |
999 input_->SetRegister(ebp.code(), reinterpret_cast<intptr_t>(frame->fp())); | 1063 input_->SetRegister(ebp.code(), reinterpret_cast<intptr_t>(frame->fp())); |
1000 for (int i = 0; i < DoubleRegister::kNumAllocatableRegisters; i++) { | 1064 for (int i = 0; i < DoubleRegister::NumAllocatableRegisters(); i++) { |
1001 input_->SetDoubleRegister(i, 0.0); | 1065 input_->SetDoubleRegister(i, 0.0); |
1002 } | 1066 } |
1003 | 1067 |
1004 // Fill the frame content from the actual data on the frame. | 1068 // Fill the frame content from the actual data on the frame. |
1005 for (unsigned i = 0; i < input_->GetFrameSize(); i += kPointerSize) { | 1069 for (unsigned i = 0; i < input_->GetFrameSize(); i += kPointerSize) { |
1006 input_->SetFrameSlot(i, Memory::uint32_at(tos + i)); | 1070 input_->SetFrameSlot(i, Memory::uint32_at(tos + i)); |
1007 } | 1071 } |
1008 } | 1072 } |
1009 | 1073 |
1010 | 1074 |
1011 #define __ masm()-> | 1075 #define __ masm()-> |
1012 | 1076 |
1013 void Deoptimizer::EntryGenerator::Generate() { | 1077 void Deoptimizer::EntryGenerator::Generate() { |
1014 GeneratePrologue(); | 1078 GeneratePrologue(); |
1015 CpuFeatures::Scope scope(SSE2); | |
1016 | 1079 |
1017 Isolate* isolate = masm()->isolate(); | 1080 Isolate* isolate = masm()->isolate(); |
1018 | 1081 |
1019 // Save all general purpose registers before messing with them. | 1082 // Save all general purpose registers before messing with them. |
1020 const int kNumberOfRegisters = Register::kNumRegisters; | 1083 const int kNumberOfRegisters = Register::kNumRegisters; |
1021 | 1084 |
1022 const int kDoubleRegsSize = kDoubleSize * | 1085 const int kDoubleRegsSize = kDoubleSize * |
1023 XMMRegister::kNumAllocatableRegisters; | 1086 XMMRegister::kNumAllocatableRegisters; |
1024 __ sub(esp, Immediate(kDoubleRegsSize)); | 1087 __ sub(esp, Immediate(kDoubleRegsSize)); |
1025 for (int i = 0; i < XMMRegister::kNumAllocatableRegisters; ++i) { | 1088 if (CpuFeatures::IsSupported(SSE2)) { |
1026 XMMRegister xmm_reg = XMMRegister::FromAllocationIndex(i); | 1089 CpuFeatures::Scope scope(SSE2); |
1027 int offset = i * kDoubleSize; | 1090 for (int i = 0; i < XMMRegister::kNumAllocatableRegisters; ++i) { |
1028 __ movdbl(Operand(esp, offset), xmm_reg); | 1091 XMMRegister xmm_reg = XMMRegister::FromAllocationIndex(i); |
| 1092 int offset = i * kDoubleSize; |
| 1093 __ movdbl(Operand(esp, offset), xmm_reg); |
| 1094 } |
1029 } | 1095 } |
1030 | 1096 |
1031 __ pushad(); | 1097 __ pushad(); |
1032 | 1098 |
1033 const int kSavedRegistersAreaSize = kNumberOfRegisters * kPointerSize + | 1099 const int kSavedRegistersAreaSize = kNumberOfRegisters * kPointerSize + |
1034 kDoubleRegsSize; | 1100 kDoubleRegsSize; |
1035 | 1101 |
1036 // Get the bailout id from the stack. | 1102 // Get the bailout id from the stack. |
1037 __ mov(ebx, Operand(esp, kSavedRegistersAreaSize)); | 1103 __ mov(ebx, Operand(esp, kSavedRegistersAreaSize)); |
1038 | 1104 |
(...skipping 27 matching lines...) Expand all Loading... |
1066 // Preserve deoptimizer object in register eax and get the input | 1132 // Preserve deoptimizer object in register eax and get the input |
1067 // frame descriptor pointer. | 1133 // frame descriptor pointer. |
1068 __ mov(ebx, Operand(eax, Deoptimizer::input_offset())); | 1134 __ mov(ebx, Operand(eax, Deoptimizer::input_offset())); |
1069 | 1135 |
1070 // Fill in the input registers. | 1136 // Fill in the input registers. |
1071 for (int i = kNumberOfRegisters - 1; i >= 0; i--) { | 1137 for (int i = kNumberOfRegisters - 1; i >= 0; i--) { |
1072 int offset = (i * kPointerSize) + FrameDescription::registers_offset(); | 1138 int offset = (i * kPointerSize) + FrameDescription::registers_offset(); |
1073 __ pop(Operand(ebx, offset)); | 1139 __ pop(Operand(ebx, offset)); |
1074 } | 1140 } |
1075 | 1141 |
1076 // Fill in the double input registers. | |
1077 int double_regs_offset = FrameDescription::double_registers_offset(); | 1142 int double_regs_offset = FrameDescription::double_registers_offset(); |
1078 for (int i = 0; i < XMMRegister::kNumAllocatableRegisters; ++i) { | 1143 if (CpuFeatures::IsSupported(SSE2)) { |
1079 int dst_offset = i * kDoubleSize + double_regs_offset; | 1144 CpuFeatures::Scope scope(SSE2); |
1080 int src_offset = i * kDoubleSize; | 1145 // Fill in the double input registers. |
1081 __ movdbl(xmm0, Operand(esp, src_offset)); | 1146 for (int i = 0; i < XMMRegister::kNumAllocatableRegisters; ++i) { |
1082 __ movdbl(Operand(ebx, dst_offset), xmm0); | 1147 int dst_offset = i * kDoubleSize + double_regs_offset; |
| 1148 int src_offset = i * kDoubleSize; |
| 1149 __ movdbl(xmm0, Operand(esp, src_offset)); |
| 1150 __ movdbl(Operand(ebx, dst_offset), xmm0); |
| 1151 } |
1083 } | 1152 } |
| 1153 __ fninit(); |
1084 | 1154 |
1085 // Remove the bailout id and the double registers from the stack. | 1155 // Remove the bailout id and the double registers from the stack. |
1086 if (type() == EAGER) { | 1156 if (type() == EAGER) { |
1087 __ add(esp, Immediate(kDoubleRegsSize + kPointerSize)); | 1157 __ add(esp, Immediate(kDoubleRegsSize + kPointerSize)); |
1088 } else { | 1158 } else { |
1089 __ add(esp, Immediate(kDoubleRegsSize + 2 * kPointerSize)); | 1159 __ add(esp, Immediate(kDoubleRegsSize + 2 * kPointerSize)); |
1090 } | 1160 } |
1091 | 1161 |
1092 // Compute a pointer to the unwinding limit in register ecx; that is | 1162 // Compute a pointer to the unwinding limit in register ecx; that is |
1093 // the first stack slot not part of the input frame. | 1163 // the first stack slot not part of the input frame. |
1094 __ mov(ecx, Operand(ebx, FrameDescription::frame_size_offset())); | 1164 __ mov(ecx, Operand(ebx, FrameDescription::frame_size_offset())); |
1095 __ add(ecx, esp); | 1165 __ add(ecx, esp); |
1096 | 1166 |
1097 // Unwind the stack down to - but not including - the unwinding | 1167 // Unwind the stack down to - but not including - the unwinding |
1098 // limit and copy the contents of the activation frame to the input | 1168 // limit and copy the contents of the activation frame to the input |
1099 // frame description. | 1169 // frame description. |
1100 __ lea(edx, Operand(ebx, FrameDescription::frame_content_offset())); | 1170 __ lea(edx, Operand(ebx, FrameDescription::frame_content_offset())); |
| 1171 Label pop_loop_header; |
| 1172 __ jmp(&pop_loop_header); |
1101 Label pop_loop; | 1173 Label pop_loop; |
1102 __ bind(&pop_loop); | 1174 __ bind(&pop_loop); |
1103 __ pop(Operand(edx, 0)); | 1175 __ pop(Operand(edx, 0)); |
1104 __ add(edx, Immediate(sizeof(uint32_t))); | 1176 __ add(edx, Immediate(sizeof(uint32_t))); |
| 1177 __ bind(&pop_loop_header); |
1105 __ cmp(ecx, esp); | 1178 __ cmp(ecx, esp); |
1106 __ j(not_equal, &pop_loop); | 1179 __ j(not_equal, &pop_loop); |
1107 | 1180 |
1108 // Compute the output frame in the deoptimizer. | 1181 // Compute the output frame in the deoptimizer. |
1109 __ push(eax); | 1182 __ push(eax); |
1110 __ PrepareCallCFunction(1, ebx); | 1183 __ PrepareCallCFunction(1, ebx); |
1111 __ mov(Operand(esp, 0 * kPointerSize), eax); | 1184 __ mov(Operand(esp, 0 * kPointerSize), eax); |
1112 { | 1185 { |
1113 AllowExternalCallThatCantCauseGC scope(masm()); | 1186 AllowExternalCallThatCantCauseGC scope(masm()); |
1114 __ CallCFunction( | 1187 __ CallCFunction( |
(...skipping 17 matching lines...) Expand all Loading... |
1132 // If frame needs dynamic alignment push padding. | 1205 // If frame needs dynamic alignment push padding. |
1133 Label no_padding; | 1206 Label no_padding; |
1134 __ cmp(Operand(eax, Deoptimizer::has_alignment_padding_offset()), | 1207 __ cmp(Operand(eax, Deoptimizer::has_alignment_padding_offset()), |
1135 Immediate(0)); | 1208 Immediate(0)); |
1136 __ j(equal, &no_padding); | 1209 __ j(equal, &no_padding); |
1137 __ push(Immediate(kAlignmentZapValue)); | 1210 __ push(Immediate(kAlignmentZapValue)); |
1138 __ bind(&no_padding); | 1211 __ bind(&no_padding); |
1139 } | 1212 } |
1140 | 1213 |
1141 // Replace the current frame with the output frames. | 1214 // Replace the current frame with the output frames. |
1142 Label outer_push_loop, inner_push_loop; | 1215 Label outer_push_loop, inner_push_loop, |
| 1216 outer_loop_header, inner_loop_header; |
1143 // Outer loop state: eax = current FrameDescription**, edx = one past the | 1217 // Outer loop state: eax = current FrameDescription**, edx = one past the |
1144 // last FrameDescription**. | 1218 // last FrameDescription**. |
1145 __ mov(edx, Operand(eax, Deoptimizer::output_count_offset())); | 1219 __ mov(edx, Operand(eax, Deoptimizer::output_count_offset())); |
1146 __ mov(eax, Operand(eax, Deoptimizer::output_offset())); | 1220 __ mov(eax, Operand(eax, Deoptimizer::output_offset())); |
1147 __ lea(edx, Operand(eax, edx, times_4, 0)); | 1221 __ lea(edx, Operand(eax, edx, times_4, 0)); |
| 1222 __ jmp(&outer_loop_header); |
1148 __ bind(&outer_push_loop); | 1223 __ bind(&outer_push_loop); |
1149 // Inner loop state: ebx = current FrameDescription*, ecx = loop index. | 1224 // Inner loop state: ebx = current FrameDescription*, ecx = loop index. |
1150 __ mov(ebx, Operand(eax, 0)); | 1225 __ mov(ebx, Operand(eax, 0)); |
1151 __ mov(ecx, Operand(ebx, FrameDescription::frame_size_offset())); | 1226 __ mov(ecx, Operand(ebx, FrameDescription::frame_size_offset())); |
| 1227 __ jmp(&inner_loop_header); |
1152 __ bind(&inner_push_loop); | 1228 __ bind(&inner_push_loop); |
1153 __ sub(ecx, Immediate(sizeof(uint32_t))); | 1229 __ sub(ecx, Immediate(sizeof(uint32_t))); |
1154 __ push(Operand(ebx, ecx, times_1, FrameDescription::frame_content_offset())); | 1230 __ push(Operand(ebx, ecx, times_1, FrameDescription::frame_content_offset())); |
| 1231 __ bind(&inner_loop_header); |
1155 __ test(ecx, ecx); | 1232 __ test(ecx, ecx); |
1156 __ j(not_zero, &inner_push_loop); | 1233 __ j(not_zero, &inner_push_loop); |
1157 __ add(eax, Immediate(kPointerSize)); | 1234 __ add(eax, Immediate(kPointerSize)); |
| 1235 __ bind(&outer_loop_header); |
1158 __ cmp(eax, edx); | 1236 __ cmp(eax, edx); |
1159 __ j(below, &outer_push_loop); | 1237 __ j(below, &outer_push_loop); |
1160 | 1238 |
1161 // In case of OSR, we have to restore the XMM registers. | 1239 // In case of OSR, we have to restore the XMM registers. |
1162 if (type() == OSR) { | 1240 if (type() == OSR) { |
1163 for (int i = 0; i < XMMRegister::kNumAllocatableRegisters; ++i) { | 1241 if (CpuFeatures::IsSupported(SSE2)) { |
1164 XMMRegister xmm_reg = XMMRegister::FromAllocationIndex(i); | 1242 CpuFeatures::Scope scope(SSE2); |
1165 int src_offset = i * kDoubleSize + double_regs_offset; | 1243 for (int i = 0; i < XMMRegister::kNumAllocatableRegisters; ++i) { |
1166 __ movdbl(xmm_reg, Operand(ebx, src_offset)); | 1244 XMMRegister xmm_reg = XMMRegister::FromAllocationIndex(i); |
| 1245 int src_offset = i * kDoubleSize + double_regs_offset; |
| 1246 __ movdbl(xmm_reg, Operand(ebx, src_offset)); |
| 1247 } |
1167 } | 1248 } |
1168 } | 1249 } |
1169 | 1250 |
1170 // Push state, pc, and continuation from the last output frame. | 1251 // Push state, pc, and continuation from the last output frame. |
1171 if (type() != OSR) { | 1252 if (type() != OSR) { |
1172 __ push(Operand(ebx, FrameDescription::state_offset())); | 1253 __ push(Operand(ebx, FrameDescription::state_offset())); |
1173 } | 1254 } |
1174 __ push(Operand(ebx, FrameDescription::pc_offset())); | 1255 __ push(Operand(ebx, FrameDescription::pc_offset())); |
1175 __ push(Operand(ebx, FrameDescription::continuation_offset())); | 1256 __ push(Operand(ebx, FrameDescription::continuation_offset())); |
1176 | 1257 |
(...skipping 24 matching lines...) Expand all Loading... |
1201 } | 1282 } |
1202 __ bind(&done); | 1283 __ bind(&done); |
1203 } | 1284 } |
1204 | 1285 |
1205 #undef __ | 1286 #undef __ |
1206 | 1287 |
1207 | 1288 |
1208 } } // namespace v8::internal | 1289 } } // namespace v8::internal |
1209 | 1290 |
1210 #endif // V8_TARGET_ARCH_IA32 | 1291 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |