Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(83)

Side by Side Diff: src/x64/lithium-codegen-x64.cc

Issue 8492004: Fix lazy deoptimization at HInvokeFunction and enable target-recording call-function stub. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: fixed missing deopt index on ARM. Created 9 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 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 25 matching lines...) Expand all
36 namespace v8 { 36 namespace v8 {
37 namespace internal { 37 namespace internal {
38 38
39 39
40 // When invoking builtins, we need to record the safepoint in the middle of 40 // When invoking builtins, we need to record the safepoint in the middle of
41 // the invoke instruction sequence generated by the macro assembler. 41 // the invoke instruction sequence generated by the macro assembler.
42 class SafepointGenerator : public CallWrapper { 42 class SafepointGenerator : public CallWrapper {
43 public: 43 public:
44 SafepointGenerator(LCodeGen* codegen, 44 SafepointGenerator(LCodeGen* codegen,
45 LPointerMap* pointers, 45 LPointerMap* pointers,
46 int deoptimization_index) 46 Safepoint::DeoptMode mode)
47 : codegen_(codegen), 47 : codegen_(codegen),
48 pointers_(pointers), 48 pointers_(pointers),
49 deoptimization_index_(deoptimization_index) { } 49 deopt_mode_(mode) { }
50 virtual ~SafepointGenerator() { } 50 virtual ~SafepointGenerator() { }
51 51
52 virtual void BeforeCall(int call_size) const { 52 virtual void BeforeCall(int call_size) const { }
53 ASSERT(call_size >= 0);
54 // Ensure that we have enough space after the previous safepoint position
55 // for the jump generated there.
56 int call_end = codegen_->masm()->pc_offset() + call_size;
57 int prev_jump_end = codegen_->LastSafepointEnd() + kMinSafepointSize;
58 if (call_end < prev_jump_end) {
59 int padding_size = prev_jump_end - call_end;
60 STATIC_ASSERT(kMinSafepointSize <= 9); // One multibyte nop is enough.
61 codegen_->masm()->nop(padding_size);
62 }
63 }
64 53
65 virtual void AfterCall() const { 54 virtual void AfterCall() const {
66 codegen_->RecordSafepoint(pointers_, deoptimization_index_); 55 codegen_->RecordSafepoint(pointers_, deopt_mode_);
67 } 56 }
68 57
69 private: 58 private:
70 static const int kMinSafepointSize =
71 MacroAssembler::kShortCallInstructionLength;
72 LCodeGen* codegen_; 59 LCodeGen* codegen_;
73 LPointerMap* pointers_; 60 LPointerMap* pointers_;
74 int deoptimization_index_; 61 Safepoint::DeoptMode deopt_mode_;
75 }; 62 };
76 63
77 64
78 #define __ masm()-> 65 #define __ masm()->
79 66
80 bool LCodeGen::GenerateCode() { 67 bool LCodeGen::GenerateCode() {
81 HPhase phase("Code generation", chunk()); 68 HPhase phase("Code generation", chunk());
82 ASSERT(is_unused()); 69 ASSERT(is_unused());
83 status_ = GENERATING; 70 status_ = GENERATING;
84 71
85 // Open a frame scope to indicate that there is a frame on the stack. The 72 // Open a frame scope to indicate that there is a frame on the stack. The
86 // MANUAL indicates that the scope shouldn't actually generate code to set up 73 // MANUAL indicates that the scope shouldn't actually generate code to set up
87 // the frame (that is done in GeneratePrologue). 74 // the frame (that is done in GeneratePrologue).
88 FrameScope frame_scope(masm_, StackFrame::MANUAL); 75 FrameScope frame_scope(masm_, StackFrame::MANUAL);
89 76
90 return GeneratePrologue() && 77 return GeneratePrologue() &&
91 GenerateBody() && 78 GenerateBody() &&
92 GenerateDeferredCode() && 79 GenerateDeferredCode() &&
93 GenerateJumpTable() && 80 GenerateJumpTable() &&
94 GenerateSafepointTable(); 81 GenerateSafepointTable();
95 } 82 }
96 83
97 84
98 void LCodeGen::FinishCode(Handle<Code> code) { 85 void LCodeGen::FinishCode(Handle<Code> code) {
99 ASSERT(is_done()); 86 ASSERT(is_done());
100 code->set_stack_slots(GetStackSlotCount()); 87 code->set_stack_slots(GetStackSlotCount());
101 code->set_safepoint_table_offset(safepoints_.GetCodeOffset()); 88 code->set_safepoint_table_offset(safepoints_.GetCodeOffset());
102 PopulateDeoptimizationData(code); 89 PopulateDeoptimizationData(code);
103 Deoptimizer::EnsureRelocSpaceForLazyDeoptimization(code);
104 } 90 }
105 91
106 92
107 void LCodeGen::Abort(const char* format, ...) { 93 void LCodeGen::Abort(const char* format, ...) {
108 if (FLAG_trace_bailout) { 94 if (FLAG_trace_bailout) {
109 SmartArrayPointer<char> name( 95 SmartArrayPointer<char> name(
110 info()->shared_info()->DebugName()->ToCString()); 96 info()->shared_info()->DebugName()->ToCString());
111 PrintF("Aborting LCodeGen in @\"%s\": ", *name); 97 PrintF("Aborting LCodeGen in @\"%s\": ", *name);
112 va_list arguments; 98 va_list arguments;
113 va_start(arguments, format); 99 va_start(arguments, format);
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
199 if (heap_slots > 0) { 185 if (heap_slots > 0) {
200 Comment(";;; Allocate local context"); 186 Comment(";;; Allocate local context");
201 // Argument to NewContext is the function, which is still in rdi. 187 // Argument to NewContext is the function, which is still in rdi.
202 __ push(rdi); 188 __ push(rdi);
203 if (heap_slots <= FastNewContextStub::kMaximumSlots) { 189 if (heap_slots <= FastNewContextStub::kMaximumSlots) {
204 FastNewContextStub stub(heap_slots); 190 FastNewContextStub stub(heap_slots);
205 __ CallStub(&stub); 191 __ CallStub(&stub);
206 } else { 192 } else {
207 __ CallRuntime(Runtime::kNewFunctionContext, 1); 193 __ CallRuntime(Runtime::kNewFunctionContext, 1);
208 } 194 }
209 RecordSafepoint(Safepoint::kNoDeoptimizationIndex); 195 RecordSafepoint(Safepoint::kNoLazyDeopt);
210 // Context is returned in both rax and rsi. It replaces the context 196 // Context is returned in both rax and rsi. It replaces the context
211 // passed to us. It's saved in the stack and kept live in rsi. 197 // passed to us. It's saved in the stack and kept live in rsi.
212 __ movq(Operand(rbp, StandardFrameConstants::kContextOffset), rsi); 198 __ movq(Operand(rbp, StandardFrameConstants::kContextOffset), rsi);
213 199
214 // Copy any necessary parameters into the context. 200 // Copy any necessary parameters into the context.
215 int num_parameters = scope()->num_parameters(); 201 int num_parameters = scope()->num_parameters();
216 for (int i = 0; i < num_parameters; i++) { 202 for (int i = 0; i < num_parameters; i++) {
217 Variable* var = scope()->parameter(i); 203 Variable* var = scope()->parameter(i);
218 if (var->IsContextSlot()) { 204 if (var->IsContextSlot()) {
219 int parameter_offset = StandardFrameConstants::kCallerSPOffset + 205 int parameter_offset = StandardFrameConstants::kCallerSPOffset +
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
252 238
253 if (emit_instructions) { 239 if (emit_instructions) {
254 Comment(";;; @%d: %s.", current_instruction_, instr->Mnemonic()); 240 Comment(";;; @%d: %s.", current_instruction_, instr->Mnemonic());
255 instr->CompileToNative(this); 241 instr->CompileToNative(this);
256 } 242 }
257 } 243 }
258 return !is_aborted(); 244 return !is_aborted();
259 } 245 }
260 246
261 247
262 LInstruction* LCodeGen::GetNextInstruction() {
263 if (current_instruction_ < instructions_->length() - 1) {
264 return instructions_->at(current_instruction_ + 1);
265 } else {
266 return NULL;
267 }
268 }
269
270
271 bool LCodeGen::GenerateJumpTable() { 248 bool LCodeGen::GenerateJumpTable() {
272 for (int i = 0; i < jump_table_.length(); i++) { 249 for (int i = 0; i < jump_table_.length(); i++) {
273 __ bind(&jump_table_[i].label); 250 __ bind(&jump_table_[i].label);
274 __ Jump(jump_table_[i].address, RelocInfo::RUNTIME_ENTRY); 251 __ Jump(jump_table_[i].address, RelocInfo::RUNTIME_ENTRY);
275 } 252 }
276 return !is_aborted(); 253 return !is_aborted();
277 } 254 }
278 255
279 256
280 bool LCodeGen::GenerateDeferredCode() { 257 bool LCodeGen::GenerateDeferredCode() {
281 ASSERT(is_generating()); 258 ASSERT(is_generating());
282 if (deferred_.length() > 0) { 259 if (deferred_.length() > 0) {
283 for (int i = 0; !is_aborted() && i < deferred_.length(); i++) { 260 for (int i = 0; !is_aborted() && i < deferred_.length(); i++) {
284 LDeferredCode* code = deferred_[i]; 261 LDeferredCode* code = deferred_[i];
285 __ bind(code->entry()); 262 __ bind(code->entry());
286 Comment(";;; Deferred code @%d: %s.", 263 Comment(";;; Deferred code @%d: %s.",
287 code->instruction_index(), 264 code->instruction_index(),
288 code->instr()->Mnemonic()); 265 code->instr()->Mnemonic());
289 code->Generate(); 266 code->Generate();
290 __ jmp(code->exit()); 267 __ jmp(code->exit());
291 } 268 }
292
293 // Pad code to ensure that the last piece of deferred code have
294 // room for lazy bailout.
295 while ((masm()->pc_offset() - LastSafepointEnd())
296 < Deoptimizer::patch_size()) {
297 int padding = masm()->pc_offset() - LastSafepointEnd();
298 if (padding > 9) {
299 __ nop(9);
300 } else {
301 __ nop(padding);
302 }
303 }
304 } 269 }
305 270
306 // Deferred code is the last part of the instruction sequence. Mark 271 // Deferred code is the last part of the instruction sequence. Mark
307 // the generated code as done unless we bailed out. 272 // the generated code as done unless we bailed out.
308 if (!is_aborted()) status_ = DONE; 273 if (!is_aborted()) status_ = DONE;
309 return !is_aborted(); 274 return !is_aborted();
310 } 275 }
311 276
312 277
313 bool LCodeGen::GenerateSafepointTable() { 278 bool LCodeGen::GenerateSafepointTable() {
314 ASSERT(is_done()); 279 ASSERT(is_done());
315 // Ensure that there is space at the end of the code to write a number
316 // of jump instructions, as well as to afford writing a call near the end
317 // of the code.
318 // The jumps are used when there isn't room in the code stream to write
319 // a long call instruction. Instead it writes a shorter call to a
320 // jump instruction in the same code object.
321 // The calls are used when lazy deoptimizing a function and calls to a
322 // deoptimization function.
323 int short_deopts = safepoints_.CountShortDeoptimizationIntervals(
324 static_cast<unsigned>(MacroAssembler::kJumpInstructionLength));
325 int byte_count = (short_deopts) * MacroAssembler::kJumpInstructionLength;
326 while (byte_count-- > 0) {
327 __ int3();
328 }
329 safepoints_.Emit(masm(), GetStackSlotCount()); 280 safepoints_.Emit(masm(), GetStackSlotCount());
330 return !is_aborted(); 281 return !is_aborted();
331 } 282 }
332 283
333 284
334 Register LCodeGen::ToRegister(int index) const { 285 Register LCodeGen::ToRegister(int index) const {
335 return Register::FromAllocationIndex(index); 286 return Register::FromAllocationIndex(index);
336 } 287 }
337 288
338 289
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
484 435
485 void LCodeGen::CallCodeGeneric(Handle<Code> code, 436 void LCodeGen::CallCodeGeneric(Handle<Code> code,
486 RelocInfo::Mode mode, 437 RelocInfo::Mode mode,
487 LInstruction* instr, 438 LInstruction* instr,
488 SafepointMode safepoint_mode, 439 SafepointMode safepoint_mode,
489 int argc) { 440 int argc) {
490 ASSERT(instr != NULL); 441 ASSERT(instr != NULL);
491 LPointerMap* pointers = instr->pointer_map(); 442 LPointerMap* pointers = instr->pointer_map();
492 RecordPosition(pointers->position()); 443 RecordPosition(pointers->position());
493 __ call(code, mode); 444 __ call(code, mode);
494 RegisterLazyDeoptimization(instr, safepoint_mode, argc); 445 RecordSafepointWithLazyDeopt(instr, safepoint_mode, argc);
495 446
496 // Signal that we don't inline smi code before these stubs in the 447 // Signal that we don't inline smi code before these stubs in the
497 // optimizing code generator. 448 // optimizing code generator.
498 if (code->kind() == Code::BINARY_OP_IC || 449 if (code->kind() == Code::BINARY_OP_IC ||
499 code->kind() == Code::COMPARE_IC) { 450 code->kind() == Code::COMPARE_IC) {
500 __ nop(); 451 __ nop();
501 } 452 }
502 } 453 }
503 454
504 455
505 void LCodeGen::CallCode(Handle<Code> code, 456 void LCodeGen::CallCode(Handle<Code> code,
506 RelocInfo::Mode mode, 457 RelocInfo::Mode mode,
507 LInstruction* instr) { 458 LInstruction* instr) {
508 CallCodeGeneric(code, mode, instr, RECORD_SIMPLE_SAFEPOINT, 0); 459 CallCodeGeneric(code, mode, instr, RECORD_SIMPLE_SAFEPOINT, 0);
509 } 460 }
510 461
511 462
512 void LCodeGen::CallRuntime(const Runtime::Function* function, 463 void LCodeGen::CallRuntime(const Runtime::Function* function,
513 int num_arguments, 464 int num_arguments,
514 LInstruction* instr) { 465 LInstruction* instr) {
515 ASSERT(instr != NULL); 466 ASSERT(instr != NULL);
516 ASSERT(instr->HasPointerMap()); 467 ASSERT(instr->HasPointerMap());
517 LPointerMap* pointers = instr->pointer_map(); 468 LPointerMap* pointers = instr->pointer_map();
518 RecordPosition(pointers->position()); 469 RecordPosition(pointers->position());
519 470
520 __ CallRuntime(function, num_arguments); 471 __ CallRuntime(function, num_arguments);
521 RegisterLazyDeoptimization(instr, RECORD_SIMPLE_SAFEPOINT, 0); 472 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT, 0);
522 } 473 }
523 474
524 475
525 void LCodeGen::CallRuntimeFromDeferred(Runtime::FunctionId id, 476 void LCodeGen::CallRuntimeFromDeferred(Runtime::FunctionId id,
526 int argc, 477 int argc,
527 LInstruction* instr) { 478 LInstruction* instr) {
528 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 479 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
529 __ CallRuntimeSaveDoubles(id); 480 __ CallRuntimeSaveDoubles(id);
530 RecordSafepointWithRegisters( 481 RecordSafepointWithRegisters(
531 instr->pointer_map(), argc, Safepoint::kNoDeoptimizationIndex); 482 instr->pointer_map(), argc, Safepoint::kNoLazyDeopt);
532 } 483 }
533 484
534 485
535 void LCodeGen::RegisterLazyDeoptimization(LInstruction* instr, 486 void LCodeGen::RegisterEnvironmentForDeoptimization(LEnvironment* environment,
536 SafepointMode safepoint_mode, 487 Safepoint::DeoptMode mode) {
537 int argc) {
538 // Create the environment to bailout to. If the call has side effects
539 // execution has to continue after the call otherwise execution can continue
540 // from a previous bailout point repeating the call.
541 LEnvironment* deoptimization_environment;
542 if (instr->HasDeoptimizationEnvironment()) {
543 deoptimization_environment = instr->deoptimization_environment();
544 } else {
545 deoptimization_environment = instr->environment();
546 }
547
548 RegisterEnvironmentForDeoptimization(deoptimization_environment);
549 if (safepoint_mode == RECORD_SIMPLE_SAFEPOINT) {
550 ASSERT(argc == 0);
551 RecordSafepoint(instr->pointer_map(),
552 deoptimization_environment->deoptimization_index());
553 } else {
554 ASSERT(safepoint_mode == RECORD_SAFEPOINT_WITH_REGISTERS);
555 RecordSafepointWithRegisters(
556 instr->pointer_map(),
557 argc,
558 deoptimization_environment->deoptimization_index());
559 }
560 }
561
562
563 void LCodeGen::RegisterEnvironmentForDeoptimization(LEnvironment* environment) {
564 if (!environment->HasBeenRegistered()) { 488 if (!environment->HasBeenRegistered()) {
565 // Physical stack frame layout: 489 // Physical stack frame layout:
566 // -x ............. -4 0 ..................................... y 490 // -x ............. -4 0 ..................................... y
567 // [incoming arguments] [spill slots] [pushed outgoing arguments] 491 // [incoming arguments] [spill slots] [pushed outgoing arguments]
568 492
569 // Layout of the environment: 493 // Layout of the environment:
570 // 0 ..................................................... size-1 494 // 0 ..................................................... size-1
571 // [parameters] [locals] [expression stack including arguments] 495 // [parameters] [locals] [expression stack including arguments]
572 496
573 // Layout of the translation: 497 // Layout of the translation:
574 // 0 ........................................................ size - 1 + 4 498 // 0 ........................................................ size - 1 + 4
575 // [expression stack including arguments] [locals] [4 words] [parameters] 499 // [expression stack including arguments] [locals] [4 words] [parameters]
576 // |>------------ translation_size ------------<| 500 // |>------------ translation_size ------------<|
577 501
578 int frame_count = 0; 502 int frame_count = 0;
579 for (LEnvironment* e = environment; e != NULL; e = e->outer()) { 503 for (LEnvironment* e = environment; e != NULL; e = e->outer()) {
580 ++frame_count; 504 ++frame_count;
581 } 505 }
582 Translation translation(&translations_, frame_count); 506 Translation translation(&translations_, frame_count);
583 WriteTranslation(environment, &translation); 507 WriteTranslation(environment, &translation);
584 int deoptimization_index = deoptimizations_.length(); 508 int deoptimization_index = deoptimizations_.length();
585 environment->Register(deoptimization_index, translation.index()); 509 int pc_offset = masm()->pc_offset();
510 environment->Register(deoptimization_index,
511 translation.index(),
512 (mode == Safepoint::kLazyDeopt) ? pc_offset : -1);
586 deoptimizations_.Add(environment); 513 deoptimizations_.Add(environment);
587 } 514 }
588 } 515 }
589 516
590 517
591 void LCodeGen::DeoptimizeIf(Condition cc, LEnvironment* environment) { 518 void LCodeGen::DeoptimizeIf(Condition cc, LEnvironment* environment) {
592 RegisterEnvironmentForDeoptimization(environment); 519 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt);
593 ASSERT(environment->HasBeenRegistered()); 520 ASSERT(environment->HasBeenRegistered());
594 int id = environment->deoptimization_index(); 521 int id = environment->deoptimization_index();
595 Address entry = Deoptimizer::GetDeoptimizationEntry(id, Deoptimizer::EAGER); 522 Address entry = Deoptimizer::GetDeoptimizationEntry(id, Deoptimizer::EAGER);
596 ASSERT(entry != NULL); 523 ASSERT(entry != NULL);
597 if (entry == NULL) { 524 if (entry == NULL) {
598 Abort("bailout was not prepared"); 525 Abort("bailout was not prepared");
599 return; 526 return;
600 } 527 }
601 528
602 if (cc == no_condition) { 529 if (cc == no_condition) {
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
634 data->SetOsrAstId(Smi::FromInt(info_->osr_ast_id())); 561 data->SetOsrAstId(Smi::FromInt(info_->osr_ast_id()));
635 data->SetOsrPcOffset(Smi::FromInt(osr_pc_offset_)); 562 data->SetOsrPcOffset(Smi::FromInt(osr_pc_offset_));
636 563
637 // Populate the deoptimization entries. 564 // Populate the deoptimization entries.
638 for (int i = 0; i < length; i++) { 565 for (int i = 0; i < length; i++) {
639 LEnvironment* env = deoptimizations_[i]; 566 LEnvironment* env = deoptimizations_[i];
640 data->SetAstId(i, Smi::FromInt(env->ast_id())); 567 data->SetAstId(i, Smi::FromInt(env->ast_id()));
641 data->SetTranslationIndex(i, Smi::FromInt(env->translation_index())); 568 data->SetTranslationIndex(i, Smi::FromInt(env->translation_index()));
642 data->SetArgumentsStackHeight(i, 569 data->SetArgumentsStackHeight(i,
643 Smi::FromInt(env->arguments_stack_height())); 570 Smi::FromInt(env->arguments_stack_height()));
571 data->SetPc(i, Smi::FromInt(env->pc_offset()));
644 } 572 }
645 code->set_deoptimization_data(*data); 573 code->set_deoptimization_data(*data);
646 } 574 }
647 575
648 576
649 int LCodeGen::DefineDeoptimizationLiteral(Handle<Object> literal) { 577 int LCodeGen::DefineDeoptimizationLiteral(Handle<Object> literal) {
650 int result = deoptimization_literals_.length(); 578 int result = deoptimization_literals_.length();
651 for (int i = 0; i < deoptimization_literals_.length(); ++i) { 579 for (int i = 0; i < deoptimization_literals_.length(); ++i) {
652 if (deoptimization_literals_[i].is_identical_to(literal)) return i; 580 if (deoptimization_literals_[i].is_identical_to(literal)) return i;
653 } 581 }
(...skipping 11 matching lines...) Expand all
665 for (int i = 0, length = inlined_closures->length(); 593 for (int i = 0, length = inlined_closures->length();
666 i < length; 594 i < length;
667 i++) { 595 i++) {
668 DefineDeoptimizationLiteral(inlined_closures->at(i)); 596 DefineDeoptimizationLiteral(inlined_closures->at(i));
669 } 597 }
670 598
671 inlined_function_count_ = deoptimization_literals_.length(); 599 inlined_function_count_ = deoptimization_literals_.length();
672 } 600 }
673 601
674 602
603 void LCodeGen::RecordSafepointWithLazyDeopt(
604 LInstruction* instr, SafepointMode safepoint_mode, int argc) {
605 if (safepoint_mode == RECORD_SIMPLE_SAFEPOINT) {
606 RecordSafepoint(instr->pointer_map(), Safepoint::kLazyDeopt);
607 } else {
608 ASSERT(safepoint_mode == RECORD_SAFEPOINT_WITH_REGISTERS);
609 RecordSafepointWithRegisters(
610 instr->pointer_map(), argc, Safepoint::kLazyDeopt);
611 }
612 }
613
614
675 void LCodeGen::RecordSafepoint( 615 void LCodeGen::RecordSafepoint(
676 LPointerMap* pointers, 616 LPointerMap* pointers,
677 Safepoint::Kind kind, 617 Safepoint::Kind kind,
678 int arguments, 618 int arguments,
679 int deoptimization_index) { 619 Safepoint::DeoptMode deopt_mode) {
680 ASSERT(kind == expected_safepoint_kind_); 620 ASSERT(kind == expected_safepoint_kind_);
681 621
682 const ZoneList<LOperand*>* operands = pointers->GetNormalizedOperands(); 622 const ZoneList<LOperand*>* operands = pointers->GetNormalizedOperands();
683 623
684 Safepoint safepoint = safepoints_.DefineSafepoint(masm(), 624 Safepoint safepoint = safepoints_.DefineSafepoint(masm(),
685 kind, arguments, deoptimization_index); 625 kind, arguments, deopt_mode);
686 for (int i = 0; i < operands->length(); i++) { 626 for (int i = 0; i < operands->length(); i++) {
687 LOperand* pointer = operands->at(i); 627 LOperand* pointer = operands->at(i);
688 if (pointer->IsStackSlot()) { 628 if (pointer->IsStackSlot()) {
689 safepoint.DefinePointerSlot(pointer->index()); 629 safepoint.DefinePointerSlot(pointer->index());
690 } else if (pointer->IsRegister() && (kind & Safepoint::kWithRegisters)) { 630 } else if (pointer->IsRegister() && (kind & Safepoint::kWithRegisters)) {
691 safepoint.DefinePointerRegister(ToRegister(pointer)); 631 safepoint.DefinePointerRegister(ToRegister(pointer));
692 } 632 }
693 } 633 }
694 if (kind & Safepoint::kWithRegisters) { 634 if (kind & Safepoint::kWithRegisters) {
695 // Register rsi always contains a pointer to the context. 635 // Register rsi always contains a pointer to the context.
696 safepoint.DefinePointerRegister(rsi); 636 safepoint.DefinePointerRegister(rsi);
697 } 637 }
698 } 638 }
699 639
700 640
701 void LCodeGen::RecordSafepoint(LPointerMap* pointers, 641 void LCodeGen::RecordSafepoint(LPointerMap* pointers,
702 int deoptimization_index) { 642 Safepoint::DeoptMode deopt_mode) {
703 RecordSafepoint(pointers, Safepoint::kSimple, 0, deoptimization_index); 643 RecordSafepoint(pointers, Safepoint::kSimple, 0, deopt_mode);
704 } 644 }
705 645
706 646
707 void LCodeGen::RecordSafepoint(int deoptimization_index) { 647 void LCodeGen::RecordSafepoint(Safepoint::DeoptMode deopt_mode) {
708 LPointerMap empty_pointers(RelocInfo::kNoPosition); 648 LPointerMap empty_pointers(RelocInfo::kNoPosition);
709 RecordSafepoint(&empty_pointers, deoptimization_index); 649 RecordSafepoint(&empty_pointers, deopt_mode);
710 } 650 }
711 651
712 652
713 void LCodeGen::RecordSafepointWithRegisters(LPointerMap* pointers, 653 void LCodeGen::RecordSafepointWithRegisters(LPointerMap* pointers,
714 int arguments, 654 int arguments,
715 int deoptimization_index) { 655 Safepoint::DeoptMode deopt_mode) {
716 RecordSafepoint(pointers, Safepoint::kWithRegisters, arguments, 656 RecordSafepoint(pointers, Safepoint::kWithRegisters, arguments, deopt_mode);
717 deoptimization_index);
718 } 657 }
719 658
720 659
721 void LCodeGen::RecordPosition(int position) { 660 void LCodeGen::RecordPosition(int position) {
722 if (position == RelocInfo::kNoPosition) return; 661 if (position == RelocInfo::kNoPosition) return;
723 masm()->positions_recorder()->RecordPosition(position); 662 masm()->positions_recorder()->RecordPosition(position);
724 } 663 }
725 664
726 665
727 void LCodeGen::DoLabel(LLabel* label) { 666 void LCodeGen::DoLabel(LLabel* label) {
(...skipping 14 matching lines...) Expand all
742 681
743 682
744 void LCodeGen::DoGap(LGap* gap) { 683 void LCodeGen::DoGap(LGap* gap) {
745 for (int i = LGap::FIRST_INNER_POSITION; 684 for (int i = LGap::FIRST_INNER_POSITION;
746 i <= LGap::LAST_INNER_POSITION; 685 i <= LGap::LAST_INNER_POSITION;
747 i++) { 686 i++) {
748 LGap::InnerPosition inner_pos = static_cast<LGap::InnerPosition>(i); 687 LGap::InnerPosition inner_pos = static_cast<LGap::InnerPosition>(i);
749 LParallelMove* move = gap->GetParallelMove(inner_pos); 688 LParallelMove* move = gap->GetParallelMove(inner_pos);
750 if (move != NULL) DoParallelMove(move); 689 if (move != NULL) DoParallelMove(move);
751 } 690 }
752
753 LInstruction* next = GetNextInstruction();
754 if (next != NULL && next->IsLazyBailout()) {
755 int pc = masm()->pc_offset();
756 safepoints_.SetPcAfterGap(pc);
757 }
758 } 691 }
759 692
760 693
761 void LCodeGen::DoInstructionGap(LInstructionGap* instr) { 694 void LCodeGen::DoInstructionGap(LInstructionGap* instr) {
762 DoGap(instr); 695 DoGap(instr);
763 } 696 }
764 697
765 698
766 void LCodeGen::DoParameter(LParameter* instr) { 699 void LCodeGen::DoParameter(LParameter* instr) {
767 // Nothing to do. 700 // Nothing to do.
(...skipping 1114 matching lines...) Expand 10 before | Expand all | Expand 10 after
1882 } 1815 }
1883 1816
1884 1817
1885 void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) { 1818 void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) {
1886 class DeferredInstanceOfKnownGlobal: public LDeferredCode { 1819 class DeferredInstanceOfKnownGlobal: public LDeferredCode {
1887 public: 1820 public:
1888 DeferredInstanceOfKnownGlobal(LCodeGen* codegen, 1821 DeferredInstanceOfKnownGlobal(LCodeGen* codegen,
1889 LInstanceOfKnownGlobal* instr) 1822 LInstanceOfKnownGlobal* instr)
1890 : LDeferredCode(codegen), instr_(instr) { } 1823 : LDeferredCode(codegen), instr_(instr) { }
1891 virtual void Generate() { 1824 virtual void Generate() {
1892 codegen()->DoDeferredLInstanceOfKnownGlobal(instr_, &map_check_); 1825 codegen()->DoDeferredInstanceOfKnownGlobal(instr_, &map_check_);
1893 } 1826 }
1894 virtual LInstruction* instr() { return instr_; } 1827 virtual LInstruction* instr() { return instr_; }
1895 Label* map_check() { return &map_check_; } 1828 Label* map_check() { return &map_check_; }
1896 private: 1829 private:
1897 LInstanceOfKnownGlobal* instr_; 1830 LInstanceOfKnownGlobal* instr_;
1898 Label map_check_; 1831 Label map_check_;
1899 }; 1832 };
1900 1833
1901 1834
1902 DeferredInstanceOfKnownGlobal* deferred; 1835 DeferredInstanceOfKnownGlobal* deferred;
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
1940 __ JumpIfNotString(object, kScratchRegister, deferred->entry()); 1873 __ JumpIfNotString(object, kScratchRegister, deferred->entry());
1941 1874
1942 __ bind(&false_result); 1875 __ bind(&false_result);
1943 __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex); 1876 __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex);
1944 1877
1945 __ bind(deferred->exit()); 1878 __ bind(deferred->exit());
1946 __ bind(&done); 1879 __ bind(&done);
1947 } 1880 }
1948 1881
1949 1882
1950 void LCodeGen::DoDeferredLInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr, 1883 void LCodeGen::DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
1951 Label* map_check) { 1884 Label* map_check) {
1952 { 1885 {
1953 PushSafepointRegistersScope scope(this); 1886 PushSafepointRegistersScope scope(this);
1954 InstanceofStub::Flags flags = static_cast<InstanceofStub::Flags>( 1887 InstanceofStub::Flags flags = static_cast<InstanceofStub::Flags>(
1955 InstanceofStub::kNoFlags | InstanceofStub::kCallSiteInlineCheck); 1888 InstanceofStub::kNoFlags | InstanceofStub::kCallSiteInlineCheck);
1956 InstanceofStub stub(flags); 1889 InstanceofStub stub(flags);
1957 1890
1958 __ push(ToRegister(instr->InputAt(0))); 1891 __ push(ToRegister(instr->InputAt(0)));
1959 __ Push(instr->function()); 1892 __ Push(instr->function());
1960 1893
1961 static const int kAdditionalDelta = 10; 1894 static const int kAdditionalDelta = 10;
1962 int delta = 1895 int delta =
1963 masm_->SizeOfCodeGeneratedSince(map_check) + kAdditionalDelta; 1896 masm_->SizeOfCodeGeneratedSince(map_check) + kAdditionalDelta;
1964 ASSERT(delta >= 0); 1897 ASSERT(delta >= 0);
1965 __ push_imm32(delta); 1898 __ push_imm32(delta);
1966 1899
1967 // We are pushing three values on the stack but recording a 1900 // We are pushing three values on the stack but recording a
1968 // safepoint with two arguments because stub is going to 1901 // safepoint with two arguments because stub is going to
1969 // remove the third argument from the stack before jumping 1902 // remove the third argument from the stack before jumping
1970 // to instanceof builtin on the slow path. 1903 // to instanceof builtin on the slow path.
1971 CallCodeGeneric(stub.GetCode(), 1904 CallCodeGeneric(stub.GetCode(),
1972 RelocInfo::CODE_TARGET, 1905 RelocInfo::CODE_TARGET,
1973 instr, 1906 instr,
1974 RECORD_SAFEPOINT_WITH_REGISTERS, 1907 RECORD_SAFEPOINT_WITH_REGISTERS,
1975 2); 1908 2);
1976 ASSERT(delta == masm_->SizeOfCodeGeneratedSince(map_check)); 1909 ASSERT(delta == masm_->SizeOfCodeGeneratedSince(map_check));
1910 ASSERT(instr->HasDeoptimizationEnvironment());
1911 LEnvironment* env = instr->deoptimization_environment();
1912 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index());
1977 // Move result to a register that survives the end of the 1913 // Move result to a register that survives the end of the
1978 // PushSafepointRegisterScope. 1914 // PushSafepointRegisterScope.
1979 __ movq(kScratchRegister, rax); 1915 __ movq(kScratchRegister, rax);
1980 } 1916 }
1981 __ testq(kScratchRegister, kScratchRegister); 1917 __ testq(kScratchRegister, kScratchRegister);
1982 Label load_false; 1918 Label load_false;
1983 Label done; 1919 Label done;
1984 __ j(not_zero, &load_false); 1920 __ j(not_zero, &load_false);
1985 __ LoadRoot(rax, Heap::kTrueValueRootIndex); 1921 __ LoadRoot(rax, Heap::kTrueValueRootIndex);
1986 __ jmp(&done); 1922 __ jmp(&done);
(...skipping 575 matching lines...) Expand 10 before | Expand all | Expand 10 after
2562 __ j(zero, &invoke, Label::kNear); 2498 __ j(zero, &invoke, Label::kNear);
2563 __ bind(&loop); 2499 __ bind(&loop);
2564 __ push(Operand(elements, length, times_pointer_size, 1 * kPointerSize)); 2500 __ push(Operand(elements, length, times_pointer_size, 1 * kPointerSize));
2565 __ decl(length); 2501 __ decl(length);
2566 __ j(not_zero, &loop); 2502 __ j(not_zero, &loop);
2567 2503
2568 // Invoke the function. 2504 // Invoke the function.
2569 __ bind(&invoke); 2505 __ bind(&invoke);
2570 ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment()); 2506 ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment());
2571 LPointerMap* pointers = instr->pointer_map(); 2507 LPointerMap* pointers = instr->pointer_map();
2572 LEnvironment* env = instr->deoptimization_environment();
2573 RecordPosition(pointers->position()); 2508 RecordPosition(pointers->position());
2574 RegisterEnvironmentForDeoptimization(env); 2509 SafepointGenerator safepoint_generator(
2575 SafepointGenerator safepoint_generator(this, 2510 this, pointers, Safepoint::kLazyDeopt);
2576 pointers,
2577 env->deoptimization_index());
2578 v8::internal::ParameterCount actual(rax); 2511 v8::internal::ParameterCount actual(rax);
2579 __ InvokeFunction(function, actual, CALL_FUNCTION, 2512 __ InvokeFunction(function, actual, CALL_FUNCTION,
2580 safepoint_generator, CALL_AS_METHOD); 2513 safepoint_generator, CALL_AS_METHOD);
2581 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 2514 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
2582 } 2515 }
2583 2516
2584 2517
2585 void LCodeGen::DoPushArgument(LPushArgument* instr) { 2518 void LCodeGen::DoPushArgument(LPushArgument* instr) {
2586 LOperand* argument = instr->InputAt(0); 2519 LOperand* argument = instr->InputAt(0);
2587 EmitPushTaggedOperand(argument); 2520 EmitPushTaggedOperand(argument);
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
2645 2578
2646 // Invoke function. 2579 // Invoke function.
2647 __ SetCallKind(rcx, call_kind); 2580 __ SetCallKind(rcx, call_kind);
2648 if (*function == *info()->closure()) { 2581 if (*function == *info()->closure()) {
2649 __ CallSelf(); 2582 __ CallSelf();
2650 } else { 2583 } else {
2651 __ call(FieldOperand(rdi, JSFunction::kCodeEntryOffset)); 2584 __ call(FieldOperand(rdi, JSFunction::kCodeEntryOffset));
2652 } 2585 }
2653 2586
2654 // Setup deoptimization. 2587 // Setup deoptimization.
2655 RegisterLazyDeoptimization(instr, RECORD_SIMPLE_SAFEPOINT, 0); 2588 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT, 0);
2656 2589
2657 // Restore context. 2590 // Restore context.
2658 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 2591 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
2659 } 2592 }
2660 2593
2661 2594
2662 void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { 2595 void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) {
2663 ASSERT(ToRegister(instr->result()).is(rax)); 2596 ASSERT(ToRegister(instr->result()).is(rax));
2664 __ Move(rdi, instr->function()); 2597 __ Move(rdi, instr->function());
2665 CallKnownFunction(instr->function(), 2598 CallKnownFunction(instr->function(),
(...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after
2993 UNREACHABLE(); 2926 UNREACHABLE();
2994 } 2927 }
2995 } 2928 }
2996 2929
2997 2930
2998 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { 2931 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) {
2999 ASSERT(ToRegister(instr->function()).is(rdi)); 2932 ASSERT(ToRegister(instr->function()).is(rdi));
3000 ASSERT(instr->HasPointerMap()); 2933 ASSERT(instr->HasPointerMap());
3001 ASSERT(instr->HasDeoptimizationEnvironment()); 2934 ASSERT(instr->HasDeoptimizationEnvironment());
3002 LPointerMap* pointers = instr->pointer_map(); 2935 LPointerMap* pointers = instr->pointer_map();
3003 LEnvironment* env = instr->deoptimization_environment();
3004 RecordPosition(pointers->position()); 2936 RecordPosition(pointers->position());
3005 RegisterEnvironmentForDeoptimization(env); 2937 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt);
3006 SafepointGenerator generator(this, pointers, env->deoptimization_index());
3007 ParameterCount count(instr->arity()); 2938 ParameterCount count(instr->arity());
3008 __ InvokeFunction(rdi, count, CALL_FUNCTION, generator, CALL_AS_METHOD); 2939 __ InvokeFunction(rdi, count, CALL_FUNCTION, generator, CALL_AS_METHOD);
3009 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 2940 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
3010 } 2941 }
3011 2942
3012 2943
3013 void LCodeGen::DoCallKeyed(LCallKeyed* instr) { 2944 void LCodeGen::DoCallKeyed(LCallKeyed* instr) {
3014 ASSERT(ToRegister(instr->key()).is(rcx)); 2945 ASSERT(ToRegister(instr->key()).is(rcx));
3015 ASSERT(ToRegister(instr->result()).is(rax)); 2946 ASSERT(ToRegister(instr->result()).is(rax));
3016 2947
(...skipping 1158 matching lines...) Expand 10 before | Expand all | Expand 10 after
4175 __ movq(temp, Operand(rax, StandardFrameConstants::kCallerFPOffset)); 4106 __ movq(temp, Operand(rax, StandardFrameConstants::kCallerFPOffset));
4176 4107
4177 // Check the marker in the calling frame. 4108 // Check the marker in the calling frame.
4178 __ bind(&check_frame_marker); 4109 __ bind(&check_frame_marker);
4179 __ Cmp(Operand(temp, StandardFrameConstants::kMarkerOffset), 4110 __ Cmp(Operand(temp, StandardFrameConstants::kMarkerOffset),
4180 Smi::FromInt(StackFrame::CONSTRUCT)); 4111 Smi::FromInt(StackFrame::CONSTRUCT));
4181 } 4112 }
4182 4113
4183 4114
4184 void LCodeGen::DoLazyBailout(LLazyBailout* instr) { 4115 void LCodeGen::DoLazyBailout(LLazyBailout* instr) {
4185 // No code for lazy bailout instruction. Used to capture environment after a 4116 // Ensure that we have enough space after the previous lazy-deoopt position
4186 // call for populating the safepoint data with deoptimization data. 4117 // for the jump generated there.
4118 int current_pc = masm()->pc_offset();
4119 int patch_size = Deoptimizer::patch_size();
4120 if (current_pc < last_lazy_deopt_pc_ + patch_size) {
4121 __ nop(last_lazy_deopt_pc_ + patch_size - current_pc);
4122 }
4123 last_lazy_deopt_pc_ = current_pc;
4124
4125 ASSERT(instr->HasEnvironment());
4126 LEnvironment* env = instr->environment();
4127 RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt);
4128 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index());
Vyacheslav Egorov (Chromium) 2011/11/15 12:03:56 This code does not pad the last @lazy-bailout in t
fschneider 2011/11/15 13:35:24 Done.
4187 } 4129 }
4188 4130
4189 4131
4190 void LCodeGen::DoDeoptimize(LDeoptimize* instr) { 4132 void LCodeGen::DoDeoptimize(LDeoptimize* instr) {
4191 DeoptimizeIf(no_condition, instr->environment()); 4133 DeoptimizeIf(no_condition, instr->environment());
4192 } 4134 }
4193 4135
4194 4136
4195 void LCodeGen::DoDeleteProperty(LDeleteProperty* instr) { 4137 void LCodeGen::DoDeleteProperty(LDeleteProperty* instr) {
4196 LOperand* obj = instr->object(); 4138 LOperand* obj = instr->object();
4197 LOperand* key = instr->key(); 4139 LOperand* key = instr->key();
4198 EmitPushTaggedOperand(obj); 4140 EmitPushTaggedOperand(obj);
4199 EmitPushTaggedOperand(key); 4141 EmitPushTaggedOperand(key);
4200 ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment()); 4142 ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment());
4201 LPointerMap* pointers = instr->pointer_map(); 4143 LPointerMap* pointers = instr->pointer_map();
4202 LEnvironment* env = instr->deoptimization_environment();
4203 RecordPosition(pointers->position()); 4144 RecordPosition(pointers->position());
4204 RegisterEnvironmentForDeoptimization(env);
4205 // Create safepoint generator that will also ensure enough space in the 4145 // Create safepoint generator that will also ensure enough space in the
4206 // reloc info for patching in deoptimization (since this is invoking a 4146 // reloc info for patching in deoptimization (since this is invoking a
4207 // builtin) 4147 // builtin)
4208 SafepointGenerator safepoint_generator(this, 4148 SafepointGenerator safepoint_generator(
4209 pointers, 4149 this, pointers, Safepoint::kLazyDeopt);
4210 env->deoptimization_index());
4211 __ Push(Smi::FromInt(strict_mode_flag())); 4150 __ Push(Smi::FromInt(strict_mode_flag()));
4212 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, safepoint_generator); 4151 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, safepoint_generator);
4213 } 4152 }
4214 4153
4215 4154
4216 void LCodeGen::DoIn(LIn* instr) { 4155 void LCodeGen::DoIn(LIn* instr) {
4217 LOperand* obj = instr->object(); 4156 LOperand* obj = instr->object();
4218 LOperand* key = instr->key(); 4157 LOperand* key = instr->key();
4219 EmitPushTaggedOperand(key); 4158 EmitPushTaggedOperand(key);
4220 EmitPushTaggedOperand(obj); 4159 EmitPushTaggedOperand(obj);
4221 ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment()); 4160 ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment());
4222 LPointerMap* pointers = instr->pointer_map(); 4161 LPointerMap* pointers = instr->pointer_map();
4223 LEnvironment* env = instr->deoptimization_environment();
4224 RecordPosition(pointers->position()); 4162 RecordPosition(pointers->position());
4225 RegisterEnvironmentForDeoptimization(env); 4163 SafepointGenerator safepoint_generator(
4226 // Create safepoint generator that will also ensure enough space in the 4164 this, pointers, Safepoint::kLazyDeopt);
4227 // reloc info for patching in deoptimization (since this is invoking a
4228 // builtin)
4229 SafepointGenerator safepoint_generator(this,
4230 pointers,
4231 env->deoptimization_index());
4232 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION, safepoint_generator); 4165 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION, safepoint_generator);
4233 } 4166 }
4234 4167
4235 4168
4236 void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) { 4169 void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) {
4237 { 4170 PushSafepointRegistersScope scope(this);
4238 PushSafepointRegistersScope scope(this); 4171 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
4239 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 4172 __ CallRuntimeSaveDoubles(Runtime::kStackGuard);
4240 __ CallRuntimeSaveDoubles(Runtime::kStackGuard); 4173 RecordSafepointWithLazyDeopt(instr, RECORD_SAFEPOINT_WITH_REGISTERS, 0);
4241 RegisterLazyDeoptimization(instr, RECORD_SAFEPOINT_WITH_REGISTERS, 0); 4174 ASSERT(instr->HasEnvironment());
4242 } 4175 LEnvironment* env = instr->environment();
4243 4176 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index());
4244 // The gap code includes the restoring of the safepoint registers.
4245 int pc = masm()->pc_offset();
4246 safepoints_.SetPcAfterGap(pc);
4247 } 4177 }
4248 4178
4249 4179
4250 void LCodeGen::DoStackCheck(LStackCheck* instr) { 4180 void LCodeGen::DoStackCheck(LStackCheck* instr) {
4251 class DeferredStackCheck: public LDeferredCode { 4181 class DeferredStackCheck: public LDeferredCode {
4252 public: 4182 public:
4253 DeferredStackCheck(LCodeGen* codegen, LStackCheck* instr) 4183 DeferredStackCheck(LCodeGen* codegen, LStackCheck* instr)
4254 : LDeferredCode(codegen), instr_(instr) { } 4184 : LDeferredCode(codegen), instr_(instr) { }
4255 virtual void Generate() { codegen()->DoDeferredStackCheck(instr_); } 4185 virtual void Generate() { codegen()->DoDeferredStackCheck(instr_); }
4256 virtual LInstruction* instr() { return instr_; } 4186 virtual LInstruction* instr() { return instr_; }
4257 private: 4187 private:
4258 LStackCheck* instr_; 4188 LStackCheck* instr_;
4259 }; 4189 };
4260 4190
4191 ASSERT(instr->HasEnvironment());
4192 LEnvironment* env = instr->environment();
4261 if (instr->hydrogen()->is_function_entry()) { 4193 if (instr->hydrogen()->is_function_entry()) {
4262 // Perform stack overflow check. 4194 // Perform stack overflow check.
4263 Label done; 4195 Label done;
4264 __ CompareRoot(rsp, Heap::kStackLimitRootIndex); 4196 __ CompareRoot(rsp, Heap::kStackLimitRootIndex);
4265 __ j(above_equal, &done, Label::kNear); 4197 __ j(above_equal, &done, Label::kNear);
4266 StackCheckStub stub; 4198 StackCheckStub stub;
4267 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 4199 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
4268 __ bind(&done); 4200 __ bind(&done);
4201 RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt);
4202 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index());
4269 } else { 4203 } else {
4270 ASSERT(instr->hydrogen()->is_backwards_branch()); 4204 ASSERT(instr->hydrogen()->is_backwards_branch());
4271 // Perform stack overflow check if this goto needs it before jumping. 4205 // Perform stack overflow check if this goto needs it before jumping.
4272 DeferredStackCheck* deferred_stack_check = 4206 DeferredStackCheck* deferred_stack_check =
4273 new DeferredStackCheck(this, instr); 4207 new DeferredStackCheck(this, instr);
4274 __ CompareRoot(rsp, Heap::kStackLimitRootIndex); 4208 __ CompareRoot(rsp, Heap::kStackLimitRootIndex);
4275 __ j(below, deferred_stack_check->entry()); 4209 __ j(below, deferred_stack_check->entry());
4276 __ bind(instr->done_label()); 4210 __ bind(instr->done_label());
4277 deferred_stack_check->SetExit(instr->done_label()); 4211 deferred_stack_check->SetExit(instr->done_label());
4212 RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt);
4213 // Don't record a deoptimization index for the safepoint here.
4214 // This will be done explicitly when emitting call and the safepoint in
4215 // the deferred code.
4278 } 4216 }
4279 } 4217 }
4280 4218
4281 4219
4282 void LCodeGen::DoOsrEntry(LOsrEntry* instr) { 4220 void LCodeGen::DoOsrEntry(LOsrEntry* instr) {
4283 // This is a pseudo-instruction that ensures that the environment here is 4221 // This is a pseudo-instruction that ensures that the environment here is
4284 // properly registered for deoptimization and records the assembler's PC 4222 // properly registered for deoptimization and records the assembler's PC
4285 // offset. 4223 // offset.
4286 LEnvironment* environment = instr->environment(); 4224 LEnvironment* environment = instr->environment();
4287 environment->SetSpilledRegisters(instr->SpilledRegisterArray(), 4225 environment->SetSpilledRegisters(instr->SpilledRegisterArray(),
4288 instr->SpilledDoubleRegisterArray()); 4226 instr->SpilledDoubleRegisterArray());
4289 4227
4290 // If the environment were already registered, we would have no way of 4228 // If the environment were already registered, we would have no way of
4291 // backpatching it with the spill slot operands. 4229 // backpatching it with the spill slot operands.
4292 ASSERT(!environment->HasBeenRegistered()); 4230 ASSERT(!environment->HasBeenRegistered());
4293 RegisterEnvironmentForDeoptimization(environment); 4231 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt);
4294 ASSERT(osr_pc_offset_ == -1); 4232 ASSERT(osr_pc_offset_ == -1);
4295 osr_pc_offset_ = masm()->pc_offset(); 4233 osr_pc_offset_ = masm()->pc_offset();
4296 } 4234 }
4297 4235
4298 #undef __ 4236 #undef __
4299 4237
4300 } } // namespace v8::internal 4238 } } // namespace v8::internal
4301 4239
4302 #endif // V8_TARGET_ARCH_X64 4240 #endif // V8_TARGET_ARCH_X64
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698