| OLD | NEW |
| 1 | 1 |
| 2 // Copyright 2011 the V8 project authors. All rights reserved. | 2 // Copyright 2011 the V8 project authors. All rights reserved. |
| 3 // Redistribution and use in source and binary forms, with or without | 3 // Redistribution and use in source and binary forms, with or without |
| 4 // modification, are permitted provided that the following conditions are | 4 // modification, are permitted provided that the following conditions are |
| 5 // met: | 5 // met: |
| 6 // | 6 // |
| 7 // * Redistributions of source code must retain the above copyright | 7 // * Redistributions of source code must retain the above copyright |
| 8 // notice, this list of conditions and the following disclaimer. | 8 // notice, this list of conditions and the following disclaimer. |
| 9 // * Redistributions in binary form must reproduce the above | 9 // * Redistributions in binary form must reproduce the above |
| 10 // copyright notice, this list of conditions and the following | 10 // copyright notice, this list of conditions and the following |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 42 return kCallInstructionSizeInWords * Assembler::kInstrSize; | 42 return kCallInstructionSizeInWords * Assembler::kInstrSize; |
| 43 } | 43 } |
| 44 | 44 |
| 45 | 45 |
| 46 void Deoptimizer::PatchCodeForDeoptimization(Isolate* isolate, Code* code) { | 46 void Deoptimizer::PatchCodeForDeoptimization(Isolate* isolate, Code* code) { |
| 47 Address code_start_address = code->instruction_start(); | 47 Address code_start_address = code->instruction_start(); |
| 48 // Invalidate the relocation information, as it will become invalid by the | 48 // Invalidate the relocation information, as it will become invalid by the |
| 49 // code patching below, and is not needed any more. | 49 // code patching below, and is not needed any more. |
| 50 code->InvalidateRelocation(); | 50 code->InvalidateRelocation(); |
| 51 | 51 |
| 52 // For each LLazyBailout instruction insert a call to the corresponding | 52 if (FLAG_zap_code_space) { |
| 53 // deoptimization entry. | 53 // Fail hard and early if we enter this code object again. |
| 54 byte* pointer = code->FindCodeAgeSequence(); |
| 55 if (pointer != NULL) { |
| 56 pointer += kNoCodeAgeSequenceLength * Assembler::kInstrSize; |
| 57 } else { |
| 58 pointer = code->instruction_start(); |
| 59 } |
| 60 CodePatcher patcher(pointer, 1); |
| 61 patcher.masm()->break_(0xCC); |
| 62 |
| 63 DeoptimizationInputData* data = |
| 64 DeoptimizationInputData::cast(code->deoptimization_data()); |
| 65 int osr_offset = data->OsrPcOffset()->value(); |
| 66 if (osr_offset > 0) { |
| 67 CodePatcher osr_patcher(code->instruction_start() + osr_offset, 1); |
| 68 osr_patcher.masm()->break_(0xCC); |
| 69 } |
| 70 } |
| 71 |
| 54 DeoptimizationInputData* deopt_data = | 72 DeoptimizationInputData* deopt_data = |
| 55 DeoptimizationInputData::cast(code->deoptimization_data()); | 73 DeoptimizationInputData::cast(code->deoptimization_data()); |
| 74 SharedFunctionInfo* shared = |
| 75 SharedFunctionInfo::cast(deopt_data->SharedFunctionInfo()); |
| 76 shared->EvictFromOptimizedCodeMap(code, "deoptimized code"); |
| 56 #ifdef DEBUG | 77 #ifdef DEBUG |
| 57 Address prev_call_address = NULL; | 78 Address prev_call_address = NULL; |
| 58 #endif | 79 #endif |
| 80 // For each LLazyBailout instruction insert a call to the corresponding |
| 81 // deoptimization entry. |
| 59 for (int i = 0; i < deopt_data->DeoptCount(); i++) { | 82 for (int i = 0; i < deopt_data->DeoptCount(); i++) { |
| 60 if (deopt_data->Pc(i)->value() == -1) continue; | 83 if (deopt_data->Pc(i)->value() == -1) continue; |
| 61 Address call_address = code_start_address + deopt_data->Pc(i)->value(); | 84 Address call_address = code_start_address + deopt_data->Pc(i)->value(); |
| 62 Address deopt_entry = GetDeoptimizationEntry(isolate, i, LAZY); | 85 Address deopt_entry = GetDeoptimizationEntry(isolate, i, LAZY); |
| 63 int call_size_in_bytes = MacroAssembler::CallSize(deopt_entry, | 86 int call_size_in_bytes = MacroAssembler::CallSize(deopt_entry, |
| 64 RelocInfo::NONE32); | 87 RelocInfo::NONE32); |
| 65 int call_size_in_words = call_size_in_bytes / Assembler::kInstrSize; | 88 int call_size_in_words = call_size_in_bytes / Assembler::kInstrSize; |
| 66 ASSERT(call_size_in_bytes % Assembler::kInstrSize == 0); | 89 ASSERT(call_size_in_bytes % Assembler::kInstrSize == 0); |
| 67 ASSERT(call_size_in_bytes <= patch_size()); | 90 ASSERT(call_size_in_bytes <= patch_size()); |
| 68 CodePatcher patcher(call_address, call_size_in_words); | 91 CodePatcher patcher(call_address, call_size_in_words); |
| (...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 232 // the first stack slot not part of the input frame. | 255 // the first stack slot not part of the input frame. |
| 233 __ lw(a2, MemOperand(a1, FrameDescription::frame_size_offset())); | 256 __ lw(a2, MemOperand(a1, FrameDescription::frame_size_offset())); |
| 234 __ Addu(a2, a2, sp); | 257 __ Addu(a2, a2, sp); |
| 235 | 258 |
| 236 // Unwind the stack down to - but not including - the unwinding | 259 // Unwind the stack down to - but not including - the unwinding |
| 237 // limit and copy the contents of the activation frame to the input | 260 // limit and copy the contents of the activation frame to the input |
| 238 // frame description. | 261 // frame description. |
| 239 __ Addu(a3, a1, Operand(FrameDescription::frame_content_offset())); | 262 __ Addu(a3, a1, Operand(FrameDescription::frame_content_offset())); |
| 240 Label pop_loop; | 263 Label pop_loop; |
| 241 Label pop_loop_header; | 264 Label pop_loop_header; |
| 242 __ Branch(&pop_loop_header); | 265 __ BranchShort(&pop_loop_header); |
| 243 __ bind(&pop_loop); | 266 __ bind(&pop_loop); |
| 244 __ pop(t0); | 267 __ pop(t0); |
| 245 __ sw(t0, MemOperand(a3, 0)); | 268 __ sw(t0, MemOperand(a3, 0)); |
| 246 __ addiu(a3, a3, sizeof(uint32_t)); | 269 __ addiu(a3, a3, sizeof(uint32_t)); |
| 247 __ bind(&pop_loop_header); | 270 __ bind(&pop_loop_header); |
| 248 __ Branch(&pop_loop, ne, a2, Operand(sp)); | 271 __ BranchShort(&pop_loop, ne, a2, Operand(sp)); |
| 249 | 272 |
| 250 // Compute the output frame in the deoptimizer. | 273 // Compute the output frame in the deoptimizer. |
| 251 __ push(a0); // Preserve deoptimizer object across call. | 274 __ push(a0); // Preserve deoptimizer object across call. |
| 252 // a0: deoptimizer object; a1: scratch. | 275 // a0: deoptimizer object; a1: scratch. |
| 253 __ PrepareCallCFunction(1, a1); | 276 __ PrepareCallCFunction(1, a1); |
| 254 // Call Deoptimizer::ComputeOutputFrames(). | 277 // Call Deoptimizer::ComputeOutputFrames(). |
| 255 { | 278 { |
| 256 AllowExternalCallThatCantCauseGC scope(masm()); | 279 AllowExternalCallThatCantCauseGC scope(masm()); |
| 257 __ CallCFunction( | 280 __ CallCFunction( |
| 258 ExternalReference::compute_output_frames_function(isolate()), 1); | 281 ExternalReference::compute_output_frames_function(isolate()), 1); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 273 // Inner loop state: a2 = current FrameDescription*, a3 = loop index. | 296 // Inner loop state: a2 = current FrameDescription*, a3 = loop index. |
| 274 __ lw(a2, MemOperand(t0, 0)); // output_[ix] | 297 __ lw(a2, MemOperand(t0, 0)); // output_[ix] |
| 275 __ lw(a3, MemOperand(a2, FrameDescription::frame_size_offset())); | 298 __ lw(a3, MemOperand(a2, FrameDescription::frame_size_offset())); |
| 276 __ jmp(&inner_loop_header); | 299 __ jmp(&inner_loop_header); |
| 277 __ bind(&inner_push_loop); | 300 __ bind(&inner_push_loop); |
| 278 __ Subu(a3, a3, Operand(sizeof(uint32_t))); | 301 __ Subu(a3, a3, Operand(sizeof(uint32_t))); |
| 279 __ Addu(t2, a2, Operand(a3)); | 302 __ Addu(t2, a2, Operand(a3)); |
| 280 __ lw(t3, MemOperand(t2, FrameDescription::frame_content_offset())); | 303 __ lw(t3, MemOperand(t2, FrameDescription::frame_content_offset())); |
| 281 __ push(t3); | 304 __ push(t3); |
| 282 __ bind(&inner_loop_header); | 305 __ bind(&inner_loop_header); |
| 283 __ Branch(&inner_push_loop, ne, a3, Operand(zero_reg)); | 306 __ BranchShort(&inner_push_loop, ne, a3, Operand(zero_reg)); |
| 284 | 307 |
| 285 __ Addu(t0, t0, Operand(kPointerSize)); | 308 __ Addu(t0, t0, Operand(kPointerSize)); |
| 286 __ bind(&outer_loop_header); | 309 __ bind(&outer_loop_header); |
| 287 __ Branch(&outer_push_loop, lt, t0, Operand(a1)); | 310 __ BranchShort(&outer_push_loop, lt, t0, Operand(a1)); |
| 288 | 311 |
| 289 __ lw(a1, MemOperand(a0, Deoptimizer::input_offset())); | 312 __ lw(a1, MemOperand(a0, Deoptimizer::input_offset())); |
| 290 for (int i = 0; i < FPURegister::kMaxNumAllocatableRegisters; ++i) { | 313 for (int i = 0; i < FPURegister::kMaxNumAllocatableRegisters; ++i) { |
| 291 const FPURegister fpu_reg = FPURegister::FromAllocationIndex(i); | 314 const FPURegister fpu_reg = FPURegister::FromAllocationIndex(i); |
| 292 int src_offset = i * kDoubleSize + double_regs_offset; | 315 int src_offset = i * kDoubleSize + double_regs_offset; |
| 293 __ ldc1(fpu_reg, MemOperand(a1, src_offset)); | 316 __ ldc1(fpu_reg, MemOperand(a1, src_offset)); |
| 294 } | 317 } |
| 295 | 318 |
| 296 // Push state, pc, and continuation from the last output frame. | 319 // Push state, pc, and continuation from the last output frame. |
| 297 __ lw(t2, MemOperand(a2, FrameDescription::state_offset())); | 320 __ lw(t2, MemOperand(a2, FrameDescription::state_offset())); |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 368 | 391 |
| 369 void FrameDescription::SetCallerFp(unsigned offset, intptr_t value) { | 392 void FrameDescription::SetCallerFp(unsigned offset, intptr_t value) { |
| 370 SetFrameSlot(offset, value); | 393 SetFrameSlot(offset, value); |
| 371 } | 394 } |
| 372 | 395 |
| 373 | 396 |
| 374 #undef __ | 397 #undef __ |
| 375 | 398 |
| 376 | 399 |
| 377 } } // namespace v8::internal | 400 } } // namespace v8::internal |
| OLD | NEW |