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

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

Issue 9215010: Merge r10006, r10087 and r10126 from bleeding edge to the 3.6 branch. (Closed) Base URL: http://v8.googlecode.com/svn/branches/3.6/
Patch Set: Created 8 years, 11 months 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
« no previous file with comments | « src/x64/lithium-codegen-x64.h ('k') | test/mjsunit/compiler/regress-funcaller.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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); 53 codegen_->EnsureSpaceForLazyDeopt(Deoptimizer::patch_size() - call_size);
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 } 54 }
64 55
65 virtual void AfterCall() const { 56 virtual void AfterCall() const {
66 codegen_->RecordSafepoint(pointers_, deoptimization_index_); 57 codegen_->RecordSafepoint(pointers_, deopt_mode_);
67 } 58 }
68 59
69 private: 60 private:
70 static const int kMinSafepointSize =
71 MacroAssembler::kShortCallInstructionLength;
72 LCodeGen* codegen_; 61 LCodeGen* codegen_;
73 LPointerMap* pointers_; 62 LPointerMap* pointers_;
74 int deoptimization_index_; 63 Safepoint::DeoptMode deopt_mode_;
75 }; 64 };
76 65
77 66
78 #define __ masm()-> 67 #define __ masm()->
79 68
80 bool LCodeGen::GenerateCode() { 69 bool LCodeGen::GenerateCode() {
81 HPhase phase("Code generation", chunk()); 70 HPhase phase("Code generation", chunk());
82 ASSERT(is_unused()); 71 ASSERT(is_unused());
83 status_ = GENERATING; 72 status_ = GENERATING;
84 return GeneratePrologue() && 73 return GeneratePrologue() &&
85 GenerateBody() && 74 GenerateBody() &&
86 GenerateDeferredCode() && 75 GenerateDeferredCode() &&
87 GenerateJumpTable() && 76 GenerateJumpTable() &&
88 GenerateSafepointTable(); 77 GenerateSafepointTable();
89 } 78 }
90 79
91 80
92 void LCodeGen::FinishCode(Handle<Code> code) { 81 void LCodeGen::FinishCode(Handle<Code> code) {
93 ASSERT(is_done()); 82 ASSERT(is_done());
94 code->set_stack_slots(GetStackSlotCount()); 83 code->set_stack_slots(GetStackSlotCount());
95 code->set_safepoint_table_offset(safepoints_.GetCodeOffset()); 84 code->set_safepoint_table_offset(safepoints_.GetCodeOffset());
96 PopulateDeoptimizationData(code); 85 PopulateDeoptimizationData(code);
97 Deoptimizer::EnsureRelocSpaceForLazyDeoptimization(code);
98 } 86 }
99 87
100 88
101 void LCodeGen::Abort(const char* format, ...) { 89 void LCodeGen::Abort(const char* format, ...) {
102 if (FLAG_trace_bailout) { 90 if (FLAG_trace_bailout) {
103 SmartArrayPointer<char> name( 91 SmartArrayPointer<char> name(
104 info()->shared_info()->DebugName()->ToCString()); 92 info()->shared_info()->DebugName()->ToCString());
105 PrintF("Aborting LCodeGen in @\"%s\": ", *name); 93 PrintF("Aborting LCodeGen in @\"%s\": ", *name);
106 va_list arguments; 94 va_list arguments;
107 va_start(arguments, format); 95 va_start(arguments, format);
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
193 if (heap_slots > 0) { 181 if (heap_slots > 0) {
194 Comment(";;; Allocate local context"); 182 Comment(";;; Allocate local context");
195 // Argument to NewContext is the function, which is still in rdi. 183 // Argument to NewContext is the function, which is still in rdi.
196 __ push(rdi); 184 __ push(rdi);
197 if (heap_slots <= FastNewContextStub::kMaximumSlots) { 185 if (heap_slots <= FastNewContextStub::kMaximumSlots) {
198 FastNewContextStub stub(heap_slots); 186 FastNewContextStub stub(heap_slots);
199 __ CallStub(&stub); 187 __ CallStub(&stub);
200 } else { 188 } else {
201 __ CallRuntime(Runtime::kNewFunctionContext, 1); 189 __ CallRuntime(Runtime::kNewFunctionContext, 1);
202 } 190 }
203 RecordSafepoint(Safepoint::kNoDeoptimizationIndex); 191 RecordSafepoint(Safepoint::kNoLazyDeopt);
204 // Context is returned in both rax and rsi. It replaces the context 192 // Context is returned in both rax and rsi. It replaces the context
205 // passed to us. It's saved in the stack and kept live in rsi. 193 // passed to us. It's saved in the stack and kept live in rsi.
206 __ movq(Operand(rbp, StandardFrameConstants::kContextOffset), rsi); 194 __ movq(Operand(rbp, StandardFrameConstants::kContextOffset), rsi);
207 195
208 // Copy any necessary parameters into the context. 196 // Copy any necessary parameters into the context.
209 int num_parameters = scope()->num_parameters(); 197 int num_parameters = scope()->num_parameters();
210 for (int i = 0; i < num_parameters; i++) { 198 for (int i = 0; i < num_parameters; i++) {
211 Variable* var = scope()->parameter(i); 199 Variable* var = scope()->parameter(i);
212 if (var->IsContextSlot()) { 200 if (var->IsContextSlot()) {
213 int parameter_offset = StandardFrameConstants::kCallerSPOffset + 201 int parameter_offset = StandardFrameConstants::kCallerSPOffset +
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
245 if (instr->IsLabel()) { 233 if (instr->IsLabel()) {
246 LLabel* label = LLabel::cast(instr); 234 LLabel* label = LLabel::cast(instr);
247 emit_instructions = !label->HasReplacement(); 235 emit_instructions = !label->HasReplacement();
248 } 236 }
249 237
250 if (emit_instructions) { 238 if (emit_instructions) {
251 Comment(";;; @%d: %s.", current_instruction_, instr->Mnemonic()); 239 Comment(";;; @%d: %s.", current_instruction_, instr->Mnemonic());
252 instr->CompileToNative(this); 240 instr->CompileToNative(this);
253 } 241 }
254 } 242 }
243 EnsureSpaceForLazyDeopt(Deoptimizer::patch_size());
255 return !is_aborted(); 244 return !is_aborted();
256 } 245 }
257 246
258 247
259 LInstruction* LCodeGen::GetNextInstruction() {
260 if (current_instruction_ < instructions_->length() - 1) {
261 return instructions_->at(current_instruction_ + 1);
262 } else {
263 return NULL;
264 }
265 }
266
267
268 bool LCodeGen::GenerateJumpTable() { 248 bool LCodeGen::GenerateJumpTable() {
269 for (int i = 0; i < jump_table_.length(); i++) { 249 for (int i = 0; i < jump_table_.length(); i++) {
270 __ bind(&jump_table_[i].label); 250 __ bind(&jump_table_[i].label);
271 __ Jump(jump_table_[i].address, RelocInfo::RUNTIME_ENTRY); 251 __ Jump(jump_table_[i].address, RelocInfo::RUNTIME_ENTRY);
272 } 252 }
273 return !is_aborted(); 253 return !is_aborted();
274 } 254 }
275 255
276 256
277 bool LCodeGen::GenerateDeferredCode() { 257 bool LCodeGen::GenerateDeferredCode() {
278 ASSERT(is_generating()); 258 ASSERT(is_generating());
279 if (deferred_.length() > 0) { 259 if (deferred_.length() > 0) {
280 for (int i = 0; !is_aborted() && i < deferred_.length(); i++) { 260 for (int i = 0; !is_aborted() && i < deferred_.length(); i++) {
281 LDeferredCode* code = deferred_[i]; 261 LDeferredCode* code = deferred_[i];
282 __ bind(code->entry()); 262 __ bind(code->entry());
283 code->Generate(); 263 code->Generate();
284 __ jmp(code->exit()); 264 __ jmp(code->exit());
285 } 265 }
286
287 // Pad code to ensure that the last piece of deferred code have
288 // room for lazy bailout.
289 while ((masm()->pc_offset() - LastSafepointEnd())
290 < Deoptimizer::patch_size()) {
291 int padding = masm()->pc_offset() - LastSafepointEnd();
292 if (padding > 9) {
293 __ nop(9);
294 } else {
295 __ nop(padding);
296 }
297 }
298 } 266 }
299 267
300 // Deferred code is the last part of the instruction sequence. Mark 268 // Deferred code is the last part of the instruction sequence. Mark
301 // the generated code as done unless we bailed out. 269 // the generated code as done unless we bailed out.
302 if (!is_aborted()) status_ = DONE; 270 if (!is_aborted()) status_ = DONE;
303 return !is_aborted(); 271 return !is_aborted();
304 } 272 }
305 273
306 274
307 bool LCodeGen::GenerateSafepointTable() { 275 bool LCodeGen::GenerateSafepointTable() {
308 ASSERT(is_done()); 276 ASSERT(is_done());
309 // Ensure that there is space at the end of the code to write a number
310 // of jump instructions, as well as to afford writing a call near the end
311 // of the code.
312 // The jumps are used when there isn't room in the code stream to write
313 // a long call instruction. Instead it writes a shorter call to a
314 // jump instruction in the same code object.
315 // The calls are used when lazy deoptimizing a function and calls to a
316 // deoptimization function.
317 int short_deopts = safepoints_.CountShortDeoptimizationIntervals(
318 static_cast<unsigned>(MacroAssembler::kJumpInstructionLength));
319 int byte_count = (short_deopts) * MacroAssembler::kJumpInstructionLength;
320 while (byte_count-- > 0) {
321 __ int3();
322 }
323 safepoints_.Emit(masm(), GetStackSlotCount()); 277 safepoints_.Emit(masm(), GetStackSlotCount());
324 return !is_aborted(); 278 return !is_aborted();
325 } 279 }
326 280
327 281
328 Register LCodeGen::ToRegister(int index) const { 282 Register LCodeGen::ToRegister(int index) const {
329 return Register::FromAllocationIndex(index); 283 return Register::FromAllocationIndex(index);
330 } 284 }
331 285
332 286
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
468 UNREACHABLE(); 422 UNREACHABLE();
469 } 423 }
470 } 424 }
471 425
472 426
473 void LCodeGen::CallCodeGeneric(Handle<Code> code, 427 void LCodeGen::CallCodeGeneric(Handle<Code> code,
474 RelocInfo::Mode mode, 428 RelocInfo::Mode mode,
475 LInstruction* instr, 429 LInstruction* instr,
476 SafepointMode safepoint_mode, 430 SafepointMode safepoint_mode,
477 int argc) { 431 int argc) {
432 EnsureSpaceForLazyDeopt(Deoptimizer::patch_size() - masm()->CallSize(code));
478 ASSERT(instr != NULL); 433 ASSERT(instr != NULL);
479 LPointerMap* pointers = instr->pointer_map(); 434 LPointerMap* pointers = instr->pointer_map();
480 RecordPosition(pointers->position()); 435 RecordPosition(pointers->position());
481 __ call(code, mode); 436 __ call(code, mode);
482 RegisterLazyDeoptimization(instr, safepoint_mode, argc); 437 RecordSafepointWithLazyDeopt(instr, safepoint_mode, argc);
483 438
484 // Signal that we don't inline smi code before these stubs in the 439 // Signal that we don't inline smi code before these stubs in the
485 // optimizing code generator. 440 // optimizing code generator.
486 if (code->kind() == Code::BINARY_OP_IC || 441 if (code->kind() == Code::BINARY_OP_IC ||
487 code->kind() == Code::COMPARE_IC) { 442 code->kind() == Code::COMPARE_IC) {
488 __ nop(); 443 __ nop();
489 } 444 }
490 } 445 }
491 446
492 447
493 void LCodeGen::CallCode(Handle<Code> code, 448 void LCodeGen::CallCode(Handle<Code> code,
494 RelocInfo::Mode mode, 449 RelocInfo::Mode mode,
495 LInstruction* instr) { 450 LInstruction* instr) {
496 CallCodeGeneric(code, mode, instr, RECORD_SIMPLE_SAFEPOINT, 0); 451 CallCodeGeneric(code, mode, instr, RECORD_SIMPLE_SAFEPOINT, 0);
497 } 452 }
498 453
499 454
500 void LCodeGen::CallRuntime(const Runtime::Function* function, 455 void LCodeGen::CallRuntime(const Runtime::Function* function,
501 int num_arguments, 456 int num_arguments,
502 LInstruction* instr) { 457 LInstruction* instr) {
503 ASSERT(instr != NULL); 458 ASSERT(instr != NULL);
504 ASSERT(instr->HasPointerMap()); 459 ASSERT(instr->HasPointerMap());
505 LPointerMap* pointers = instr->pointer_map(); 460 LPointerMap* pointers = instr->pointer_map();
506 RecordPosition(pointers->position()); 461 RecordPosition(pointers->position());
507 462
508 __ CallRuntime(function, num_arguments); 463 __ CallRuntime(function, num_arguments);
509 RegisterLazyDeoptimization(instr, RECORD_SIMPLE_SAFEPOINT, 0); 464 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT, 0);
510 } 465 }
511 466
512 467
513 void LCodeGen::CallRuntimeFromDeferred(Runtime::FunctionId id, 468 void LCodeGen::CallRuntimeFromDeferred(Runtime::FunctionId id,
514 int argc, 469 int argc,
515 LInstruction* instr) { 470 LInstruction* instr) {
516 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 471 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
517 __ CallRuntimeSaveDoubles(id); 472 __ CallRuntimeSaveDoubles(id);
518 RecordSafepointWithRegisters( 473 RecordSafepointWithRegisters(
519 instr->pointer_map(), argc, Safepoint::kNoDeoptimizationIndex); 474 instr->pointer_map(), argc, Safepoint::kNoLazyDeopt);
520 } 475 }
521 476
522 477
523 void LCodeGen::RegisterLazyDeoptimization(LInstruction* instr, 478 void LCodeGen::RegisterEnvironmentForDeoptimization(LEnvironment* environment,
524 SafepointMode safepoint_mode, 479 Safepoint::DeoptMode mode) {
525 int argc) {
526 // Create the environment to bailout to. If the call has side effects
527 // execution has to continue after the call otherwise execution can continue
528 // from a previous bailout point repeating the call.
529 LEnvironment* deoptimization_environment;
530 if (instr->HasDeoptimizationEnvironment()) {
531 deoptimization_environment = instr->deoptimization_environment();
532 } else {
533 deoptimization_environment = instr->environment();
534 }
535
536 RegisterEnvironmentForDeoptimization(deoptimization_environment);
537 if (safepoint_mode == RECORD_SIMPLE_SAFEPOINT) {
538 ASSERT(argc == 0);
539 RecordSafepoint(instr->pointer_map(),
540 deoptimization_environment->deoptimization_index());
541 } else {
542 ASSERT(safepoint_mode == RECORD_SAFEPOINT_WITH_REGISTERS);
543 RecordSafepointWithRegisters(
544 instr->pointer_map(),
545 argc,
546 deoptimization_environment->deoptimization_index());
547 }
548 }
549
550
551 void LCodeGen::RegisterEnvironmentForDeoptimization(LEnvironment* environment) {
552 if (!environment->HasBeenRegistered()) { 480 if (!environment->HasBeenRegistered()) {
553 // Physical stack frame layout: 481 // Physical stack frame layout:
554 // -x ............. -4 0 ..................................... y 482 // -x ............. -4 0 ..................................... y
555 // [incoming arguments] [spill slots] [pushed outgoing arguments] 483 // [incoming arguments] [spill slots] [pushed outgoing arguments]
556 484
557 // Layout of the environment: 485 // Layout of the environment:
558 // 0 ..................................................... size-1 486 // 0 ..................................................... size-1
559 // [parameters] [locals] [expression stack including arguments] 487 // [parameters] [locals] [expression stack including arguments]
560 488
561 // Layout of the translation: 489 // Layout of the translation:
562 // 0 ........................................................ size - 1 + 4 490 // 0 ........................................................ size - 1 + 4
563 // [expression stack including arguments] [locals] [4 words] [parameters] 491 // [expression stack including arguments] [locals] [4 words] [parameters]
564 // |>------------ translation_size ------------<| 492 // |>------------ translation_size ------------<|
565 493
566 int frame_count = 0; 494 int frame_count = 0;
567 for (LEnvironment* e = environment; e != NULL; e = e->outer()) { 495 for (LEnvironment* e = environment; e != NULL; e = e->outer()) {
568 ++frame_count; 496 ++frame_count;
569 } 497 }
570 Translation translation(&translations_, frame_count); 498 Translation translation(&translations_, frame_count);
571 WriteTranslation(environment, &translation); 499 WriteTranslation(environment, &translation);
572 int deoptimization_index = deoptimizations_.length(); 500 int deoptimization_index = deoptimizations_.length();
573 environment->Register(deoptimization_index, translation.index()); 501 int pc_offset = masm()->pc_offset();
502 environment->Register(deoptimization_index,
503 translation.index(),
504 (mode == Safepoint::kLazyDeopt) ? pc_offset : -1);
574 deoptimizations_.Add(environment); 505 deoptimizations_.Add(environment);
575 } 506 }
576 } 507 }
577 508
578 509
579 void LCodeGen::DeoptimizeIf(Condition cc, LEnvironment* environment) { 510 void LCodeGen::DeoptimizeIf(Condition cc, LEnvironment* environment) {
580 RegisterEnvironmentForDeoptimization(environment); 511 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt);
581 ASSERT(environment->HasBeenRegistered()); 512 ASSERT(environment->HasBeenRegistered());
582 int id = environment->deoptimization_index(); 513 int id = environment->deoptimization_index();
583 Address entry = Deoptimizer::GetDeoptimizationEntry(id, Deoptimizer::EAGER); 514 Address entry = Deoptimizer::GetDeoptimizationEntry(id, Deoptimizer::EAGER);
584 ASSERT(entry != NULL); 515 ASSERT(entry != NULL);
585 if (entry == NULL) { 516 if (entry == NULL) {
586 Abort("bailout was not prepared"); 517 Abort("bailout was not prepared");
587 return; 518 return;
588 } 519 }
589 520
590 if (cc == no_condition) { 521 if (cc == no_condition) {
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
622 data->SetOsrAstId(Smi::FromInt(info_->osr_ast_id())); 553 data->SetOsrAstId(Smi::FromInt(info_->osr_ast_id()));
623 data->SetOsrPcOffset(Smi::FromInt(osr_pc_offset_)); 554 data->SetOsrPcOffset(Smi::FromInt(osr_pc_offset_));
624 555
625 // Populate the deoptimization entries. 556 // Populate the deoptimization entries.
626 for (int i = 0; i < length; i++) { 557 for (int i = 0; i < length; i++) {
627 LEnvironment* env = deoptimizations_[i]; 558 LEnvironment* env = deoptimizations_[i];
628 data->SetAstId(i, Smi::FromInt(env->ast_id())); 559 data->SetAstId(i, Smi::FromInt(env->ast_id()));
629 data->SetTranslationIndex(i, Smi::FromInt(env->translation_index())); 560 data->SetTranslationIndex(i, Smi::FromInt(env->translation_index()));
630 data->SetArgumentsStackHeight(i, 561 data->SetArgumentsStackHeight(i,
631 Smi::FromInt(env->arguments_stack_height())); 562 Smi::FromInt(env->arguments_stack_height()));
563 data->SetPc(i, Smi::FromInt(env->pc_offset()));
632 } 564 }
633 code->set_deoptimization_data(*data); 565 code->set_deoptimization_data(*data);
634 } 566 }
635 567
636 568
637 int LCodeGen::DefineDeoptimizationLiteral(Handle<Object> literal) { 569 int LCodeGen::DefineDeoptimizationLiteral(Handle<Object> literal) {
638 int result = deoptimization_literals_.length(); 570 int result = deoptimization_literals_.length();
639 for (int i = 0; i < deoptimization_literals_.length(); ++i) { 571 for (int i = 0; i < deoptimization_literals_.length(); ++i) {
640 if (deoptimization_literals_[i].is_identical_to(literal)) return i; 572 if (deoptimization_literals_[i].is_identical_to(literal)) return i;
641 } 573 }
(...skipping 11 matching lines...) Expand all
653 for (int i = 0, length = inlined_closures->length(); 585 for (int i = 0, length = inlined_closures->length();
654 i < length; 586 i < length;
655 i++) { 587 i++) {
656 DefineDeoptimizationLiteral(inlined_closures->at(i)); 588 DefineDeoptimizationLiteral(inlined_closures->at(i));
657 } 589 }
658 590
659 inlined_function_count_ = deoptimization_literals_.length(); 591 inlined_function_count_ = deoptimization_literals_.length();
660 } 592 }
661 593
662 594
595 void LCodeGen::RecordSafepointWithLazyDeopt(
596 LInstruction* instr, SafepointMode safepoint_mode, int argc) {
597 if (safepoint_mode == RECORD_SIMPLE_SAFEPOINT) {
598 RecordSafepoint(instr->pointer_map(), Safepoint::kLazyDeopt);
599 } else {
600 ASSERT(safepoint_mode == RECORD_SAFEPOINT_WITH_REGISTERS);
601 RecordSafepointWithRegisters(
602 instr->pointer_map(), argc, Safepoint::kLazyDeopt);
603 }
604 }
605
606
663 void LCodeGen::RecordSafepoint( 607 void LCodeGen::RecordSafepoint(
664 LPointerMap* pointers, 608 LPointerMap* pointers,
665 Safepoint::Kind kind, 609 Safepoint::Kind kind,
666 int arguments, 610 int arguments,
667 int deoptimization_index) { 611 Safepoint::DeoptMode deopt_mode) {
668 ASSERT(kind == expected_safepoint_kind_); 612 ASSERT(kind == expected_safepoint_kind_);
669 613
670 const ZoneList<LOperand*>* operands = pointers->operands(); 614 const ZoneList<LOperand*>* operands = pointers->operands();
671 615
672 Safepoint safepoint = safepoints_.DefineSafepoint(masm(), 616 Safepoint safepoint = safepoints_.DefineSafepoint(masm(),
673 kind, arguments, deoptimization_index); 617 kind, arguments, deopt_mode);
674 for (int i = 0; i < operands->length(); i++) { 618 for (int i = 0; i < operands->length(); i++) {
675 LOperand* pointer = operands->at(i); 619 LOperand* pointer = operands->at(i);
676 if (pointer->IsStackSlot()) { 620 if (pointer->IsStackSlot()) {
677 safepoint.DefinePointerSlot(pointer->index()); 621 safepoint.DefinePointerSlot(pointer->index());
678 } else if (pointer->IsRegister() && (kind & Safepoint::kWithRegisters)) { 622 } else if (pointer->IsRegister() && (kind & Safepoint::kWithRegisters)) {
679 safepoint.DefinePointerRegister(ToRegister(pointer)); 623 safepoint.DefinePointerRegister(ToRegister(pointer));
680 } 624 }
681 } 625 }
682 if (kind & Safepoint::kWithRegisters) { 626 if (kind & Safepoint::kWithRegisters) {
683 // Register rsi always contains a pointer to the context. 627 // Register rsi always contains a pointer to the context.
684 safepoint.DefinePointerRegister(rsi); 628 safepoint.DefinePointerRegister(rsi);
685 } 629 }
686 } 630 }
687 631
688 632
689 void LCodeGen::RecordSafepoint(LPointerMap* pointers, 633 void LCodeGen::RecordSafepoint(LPointerMap* pointers,
690 int deoptimization_index) { 634 Safepoint::DeoptMode deopt_mode) {
691 RecordSafepoint(pointers, Safepoint::kSimple, 0, deoptimization_index); 635 RecordSafepoint(pointers, Safepoint::kSimple, 0, deopt_mode);
692 } 636 }
693 637
694 638
695 void LCodeGen::RecordSafepoint(int deoptimization_index) { 639 void LCodeGen::RecordSafepoint(Safepoint::DeoptMode deopt_mode) {
696 LPointerMap empty_pointers(RelocInfo::kNoPosition); 640 LPointerMap empty_pointers(RelocInfo::kNoPosition);
697 RecordSafepoint(&empty_pointers, deoptimization_index); 641 RecordSafepoint(&empty_pointers, deopt_mode);
698 } 642 }
699 643
700 644
701 void LCodeGen::RecordSafepointWithRegisters(LPointerMap* pointers, 645 void LCodeGen::RecordSafepointWithRegisters(LPointerMap* pointers,
702 int arguments, 646 int arguments,
703 int deoptimization_index) { 647 Safepoint::DeoptMode deopt_mode) {
704 RecordSafepoint(pointers, Safepoint::kWithRegisters, arguments, 648 RecordSafepoint(pointers, Safepoint::kWithRegisters, arguments, deopt_mode);
705 deoptimization_index);
706 } 649 }
707 650
708 651
709 void LCodeGen::RecordPosition(int position) { 652 void LCodeGen::RecordPosition(int position) {
710 if (position == RelocInfo::kNoPosition) return; 653 if (position == RelocInfo::kNoPosition) return;
711 masm()->positions_recorder()->RecordPosition(position); 654 masm()->positions_recorder()->RecordPosition(position);
712 } 655 }
713 656
714 657
715 void LCodeGen::DoLabel(LLabel* label) { 658 void LCodeGen::DoLabel(LLabel* label) {
(...skipping 14 matching lines...) Expand all
730 673
731 674
732 void LCodeGen::DoGap(LGap* gap) { 675 void LCodeGen::DoGap(LGap* gap) {
733 for (int i = LGap::FIRST_INNER_POSITION; 676 for (int i = LGap::FIRST_INNER_POSITION;
734 i <= LGap::LAST_INNER_POSITION; 677 i <= LGap::LAST_INNER_POSITION;
735 i++) { 678 i++) {
736 LGap::InnerPosition inner_pos = static_cast<LGap::InnerPosition>(i); 679 LGap::InnerPosition inner_pos = static_cast<LGap::InnerPosition>(i);
737 LParallelMove* move = gap->GetParallelMove(inner_pos); 680 LParallelMove* move = gap->GetParallelMove(inner_pos);
738 if (move != NULL) DoParallelMove(move); 681 if (move != NULL) DoParallelMove(move);
739 } 682 }
740
741 LInstruction* next = GetNextInstruction();
742 if (next != NULL && next->IsLazyBailout()) {
743 int pc = masm()->pc_offset();
744 safepoints_.SetPcAfterGap(pc);
745 }
746 } 683 }
747 684
748 685
749 void LCodeGen::DoInstructionGap(LInstructionGap* instr) { 686 void LCodeGen::DoInstructionGap(LInstructionGap* instr) {
750 DoGap(instr); 687 DoGap(instr);
751 } 688 }
752 689
753 690
754 void LCodeGen::DoParameter(LParameter* instr) { 691 void LCodeGen::DoParameter(LParameter* instr) {
755 // Nothing to do. 692 // Nothing to do.
(...skipping 1088 matching lines...) Expand 10 before | Expand all | Expand 10 after
1844 } 1781 }
1845 1782
1846 1783
1847 void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) { 1784 void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) {
1848 class DeferredInstanceOfKnownGlobal: public LDeferredCode { 1785 class DeferredInstanceOfKnownGlobal: public LDeferredCode {
1849 public: 1786 public:
1850 DeferredInstanceOfKnownGlobal(LCodeGen* codegen, 1787 DeferredInstanceOfKnownGlobal(LCodeGen* codegen,
1851 LInstanceOfKnownGlobal* instr) 1788 LInstanceOfKnownGlobal* instr)
1852 : LDeferredCode(codegen), instr_(instr) { } 1789 : LDeferredCode(codegen), instr_(instr) { }
1853 virtual void Generate() { 1790 virtual void Generate() {
1854 codegen()->DoDeferredLInstanceOfKnownGlobal(instr_, &map_check_); 1791 codegen()->DoDeferredInstanceOfKnownGlobal(instr_, &map_check_);
1855 } 1792 }
1856 1793
1857 Label* map_check() { return &map_check_; } 1794 Label* map_check() { return &map_check_; }
1858 1795
1859 private: 1796 private:
1860 LInstanceOfKnownGlobal* instr_; 1797 LInstanceOfKnownGlobal* instr_;
1861 Label map_check_; 1798 Label map_check_;
1862 }; 1799 };
1863 1800
1864 1801
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
1903 __ JumpIfNotString(object, kScratchRegister, deferred->entry()); 1840 __ JumpIfNotString(object, kScratchRegister, deferred->entry());
1904 1841
1905 __ bind(&false_result); 1842 __ bind(&false_result);
1906 __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex); 1843 __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex);
1907 1844
1908 __ bind(deferred->exit()); 1845 __ bind(deferred->exit());
1909 __ bind(&done); 1846 __ bind(&done);
1910 } 1847 }
1911 1848
1912 1849
1913 void LCodeGen::DoDeferredLInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr, 1850 void LCodeGen::DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
1914 Label* map_check) { 1851 Label* map_check) {
1915 { 1852 {
1916 PushSafepointRegistersScope scope(this); 1853 PushSafepointRegistersScope scope(this);
1917 InstanceofStub::Flags flags = static_cast<InstanceofStub::Flags>( 1854 InstanceofStub::Flags flags = static_cast<InstanceofStub::Flags>(
1918 InstanceofStub::kNoFlags | InstanceofStub::kCallSiteInlineCheck); 1855 InstanceofStub::kNoFlags | InstanceofStub::kCallSiteInlineCheck);
1919 InstanceofStub stub(flags); 1856 InstanceofStub stub(flags);
1920 1857
1921 __ push(ToRegister(instr->InputAt(0))); 1858 __ push(ToRegister(instr->InputAt(0)));
1922 __ Push(instr->function()); 1859 __ Push(instr->function());
1923 1860
1924 static const int kAdditionalDelta = 10; 1861 static const int kAdditionalDelta = 10;
1925 int delta = 1862 int delta =
1926 masm_->SizeOfCodeGeneratedSince(map_check) + kAdditionalDelta; 1863 masm_->SizeOfCodeGeneratedSince(map_check) + kAdditionalDelta;
1927 ASSERT(delta >= 0); 1864 ASSERT(delta >= 0);
1928 __ push_imm32(delta); 1865 __ push_imm32(delta);
1929 1866
1930 // We are pushing three values on the stack but recording a 1867 // We are pushing three values on the stack but recording a
1931 // safepoint with two arguments because stub is going to 1868 // safepoint with two arguments because stub is going to
1932 // remove the third argument from the stack before jumping 1869 // remove the third argument from the stack before jumping
1933 // to instanceof builtin on the slow path. 1870 // to instanceof builtin on the slow path.
1934 CallCodeGeneric(stub.GetCode(), 1871 CallCodeGeneric(stub.GetCode(),
1935 RelocInfo::CODE_TARGET, 1872 RelocInfo::CODE_TARGET,
1936 instr, 1873 instr,
1937 RECORD_SAFEPOINT_WITH_REGISTERS, 1874 RECORD_SAFEPOINT_WITH_REGISTERS,
1938 2); 1875 2);
1939 ASSERT(delta == masm_->SizeOfCodeGeneratedSince(map_check)); 1876 ASSERT(delta == masm_->SizeOfCodeGeneratedSince(map_check));
1877 ASSERT(instr->HasDeoptimizationEnvironment());
1878 LEnvironment* env = instr->deoptimization_environment();
1879 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index());
1940 // Move result to a register that survives the end of the 1880 // Move result to a register that survives the end of the
1941 // PushSafepointRegisterScope. 1881 // PushSafepointRegisterScope.
1942 __ movq(kScratchRegister, rax); 1882 __ movq(kScratchRegister, rax);
1943 } 1883 }
1944 __ testq(kScratchRegister, kScratchRegister); 1884 __ testq(kScratchRegister, kScratchRegister);
1945 Label load_false; 1885 Label load_false;
1946 Label done; 1886 Label done;
1947 __ j(not_zero, &load_false); 1887 __ j(not_zero, &load_false);
1948 __ LoadRoot(rax, Heap::kTrueValueRootIndex); 1888 __ LoadRoot(rax, Heap::kTrueValueRootIndex);
1949 __ jmp(&done); 1889 __ jmp(&done);
(...skipping 551 matching lines...) Expand 10 before | Expand all | Expand 10 after
2501 __ j(zero, &invoke, Label::kNear); 2441 __ j(zero, &invoke, Label::kNear);
2502 __ bind(&loop); 2442 __ bind(&loop);
2503 __ push(Operand(elements, length, times_pointer_size, 1 * kPointerSize)); 2443 __ push(Operand(elements, length, times_pointer_size, 1 * kPointerSize));
2504 __ decl(length); 2444 __ decl(length);
2505 __ j(not_zero, &loop); 2445 __ j(not_zero, &loop);
2506 2446
2507 // Invoke the function. 2447 // Invoke the function.
2508 __ bind(&invoke); 2448 __ bind(&invoke);
2509 ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment()); 2449 ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment());
2510 LPointerMap* pointers = instr->pointer_map(); 2450 LPointerMap* pointers = instr->pointer_map();
2511 LEnvironment* env = instr->deoptimization_environment();
2512 RecordPosition(pointers->position()); 2451 RecordPosition(pointers->position());
2513 RegisterEnvironmentForDeoptimization(env); 2452 SafepointGenerator safepoint_generator(
2514 SafepointGenerator safepoint_generator(this, 2453 this, pointers, Safepoint::kLazyDeopt);
2515 pointers,
2516 env->deoptimization_index());
2517 v8::internal::ParameterCount actual(rax); 2454 v8::internal::ParameterCount actual(rax);
2518 __ InvokeFunction(function, actual, CALL_FUNCTION, 2455 __ InvokeFunction(function, actual, CALL_FUNCTION,
2519 safepoint_generator, CALL_AS_METHOD); 2456 safepoint_generator, CALL_AS_METHOD);
2520 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 2457 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
2521 } 2458 }
2522 2459
2523 2460
2524 void LCodeGen::DoPushArgument(LPushArgument* instr) { 2461 void LCodeGen::DoPushArgument(LPushArgument* instr) {
2525 LOperand* argument = instr->InputAt(0); 2462 LOperand* argument = instr->InputAt(0);
2526 EmitPushTaggedOperand(argument); 2463 EmitPushTaggedOperand(argument);
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
2584 2521
2585 // Invoke function. 2522 // Invoke function.
2586 __ SetCallKind(rcx, call_kind); 2523 __ SetCallKind(rcx, call_kind);
2587 if (*function == *info()->closure()) { 2524 if (*function == *info()->closure()) {
2588 __ CallSelf(); 2525 __ CallSelf();
2589 } else { 2526 } else {
2590 __ call(FieldOperand(rdi, JSFunction::kCodeEntryOffset)); 2527 __ call(FieldOperand(rdi, JSFunction::kCodeEntryOffset));
2591 } 2528 }
2592 2529
2593 // Setup deoptimization. 2530 // Setup deoptimization.
2594 RegisterLazyDeoptimization(instr, RECORD_SIMPLE_SAFEPOINT, 0); 2531 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT, 0);
2595 2532
2596 // Restore context. 2533 // Restore context.
2597 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 2534 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
2598 } 2535 }
2599 2536
2600 2537
2601 void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { 2538 void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) {
2602 ASSERT(ToRegister(instr->result()).is(rax)); 2539 ASSERT(ToRegister(instr->result()).is(rax));
2603 __ Move(rdi, instr->function()); 2540 __ Move(rdi, instr->function());
2604 CallKnownFunction(instr->function(), 2541 CallKnownFunction(instr->function(),
(...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after
2931 UNREACHABLE(); 2868 UNREACHABLE();
2932 } 2869 }
2933 } 2870 }
2934 2871
2935 2872
2936 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { 2873 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) {
2937 ASSERT(ToRegister(instr->function()).is(rdi)); 2874 ASSERT(ToRegister(instr->function()).is(rdi));
2938 ASSERT(instr->HasPointerMap()); 2875 ASSERT(instr->HasPointerMap());
2939 ASSERT(instr->HasDeoptimizationEnvironment()); 2876 ASSERT(instr->HasDeoptimizationEnvironment());
2940 LPointerMap* pointers = instr->pointer_map(); 2877 LPointerMap* pointers = instr->pointer_map();
2941 LEnvironment* env = instr->deoptimization_environment();
2942 RecordPosition(pointers->position()); 2878 RecordPosition(pointers->position());
2943 RegisterEnvironmentForDeoptimization(env); 2879 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt);
2944 SafepointGenerator generator(this, pointers, env->deoptimization_index());
2945 ParameterCount count(instr->arity()); 2880 ParameterCount count(instr->arity());
2946 __ InvokeFunction(rdi, count, CALL_FUNCTION, generator, CALL_AS_METHOD); 2881 __ InvokeFunction(rdi, count, CALL_FUNCTION, generator, CALL_AS_METHOD);
2947 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 2882 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
2948 } 2883 }
2949 2884
2950 2885
2951 void LCodeGen::DoCallKeyed(LCallKeyed* instr) { 2886 void LCodeGen::DoCallKeyed(LCallKeyed* instr) {
2952 ASSERT(ToRegister(instr->key()).is(rcx)); 2887 ASSERT(ToRegister(instr->key()).is(rcx));
2953 ASSERT(ToRegister(instr->result()).is(rax)); 2888 ASSERT(ToRegister(instr->result()).is(rax));
2954 2889
(...skipping 1075 matching lines...) Expand 10 before | Expand all | Expand 10 after
4030 __ j(not_equal, &check_frame_marker, Label::kNear); 3965 __ j(not_equal, &check_frame_marker, Label::kNear);
4031 __ movq(temp, Operand(rax, StandardFrameConstants::kCallerFPOffset)); 3966 __ movq(temp, Operand(rax, StandardFrameConstants::kCallerFPOffset));
4032 3967
4033 // Check the marker in the calling frame. 3968 // Check the marker in the calling frame.
4034 __ bind(&check_frame_marker); 3969 __ bind(&check_frame_marker);
4035 __ Cmp(Operand(temp, StandardFrameConstants::kMarkerOffset), 3970 __ Cmp(Operand(temp, StandardFrameConstants::kMarkerOffset),
4036 Smi::FromInt(StackFrame::CONSTRUCT)); 3971 Smi::FromInt(StackFrame::CONSTRUCT));
4037 } 3972 }
4038 3973
4039 3974
3975 void LCodeGen::EnsureSpaceForLazyDeopt(int space_needed) {
3976 // Ensure that we have enough space after the previous lazy-bailout
3977 // instruction for patching the code here.
3978 int current_pc = masm()->pc_offset();
3979 if (current_pc < last_lazy_deopt_pc_ + space_needed) {
3980 int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc;
3981 while (padding_size > 0) {
3982 int nop_size = padding_size > 9 ? 9 : padding_size;
3983 __ nop(nop_size);
3984 padding_size -= nop_size;
3985 }
3986 }
3987 }
3988
3989
4040 void LCodeGen::DoLazyBailout(LLazyBailout* instr) { 3990 void LCodeGen::DoLazyBailout(LLazyBailout* instr) {
4041 // No code for lazy bailout instruction. Used to capture environment after a 3991 EnsureSpaceForLazyDeopt(Deoptimizer::patch_size());
4042 // call for populating the safepoint data with deoptimization data. 3992 last_lazy_deopt_pc_ = masm()->pc_offset();
3993 ASSERT(instr->HasEnvironment());
3994 LEnvironment* env = instr->environment();
3995 RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt);
3996 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index());
4043 } 3997 }
4044 3998
4045 3999
4046 void LCodeGen::DoDeoptimize(LDeoptimize* instr) { 4000 void LCodeGen::DoDeoptimize(LDeoptimize* instr) {
4047 DeoptimizeIf(no_condition, instr->environment()); 4001 DeoptimizeIf(no_condition, instr->environment());
4048 } 4002 }
4049 4003
4050 4004
4051 void LCodeGen::DoDeleteProperty(LDeleteProperty* instr) { 4005 void LCodeGen::DoDeleteProperty(LDeleteProperty* instr) {
4052 LOperand* obj = instr->object(); 4006 LOperand* obj = instr->object();
4053 LOperand* key = instr->key(); 4007 LOperand* key = instr->key();
4054 EmitPushTaggedOperand(obj); 4008 EmitPushTaggedOperand(obj);
4055 EmitPushTaggedOperand(key); 4009 EmitPushTaggedOperand(key);
4056 ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment()); 4010 ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment());
4057 LPointerMap* pointers = instr->pointer_map(); 4011 LPointerMap* pointers = instr->pointer_map();
4058 LEnvironment* env = instr->deoptimization_environment();
4059 RecordPosition(pointers->position()); 4012 RecordPosition(pointers->position());
4060 RegisterEnvironmentForDeoptimization(env);
4061 // Create safepoint generator that will also ensure enough space in the 4013 // Create safepoint generator that will also ensure enough space in the
4062 // reloc info for patching in deoptimization (since this is invoking a 4014 // reloc info for patching in deoptimization (since this is invoking a
4063 // builtin) 4015 // builtin)
4064 SafepointGenerator safepoint_generator(this, 4016 SafepointGenerator safepoint_generator(
4065 pointers, 4017 this, pointers, Safepoint::kLazyDeopt);
4066 env->deoptimization_index());
4067 __ Push(Smi::FromInt(strict_mode_flag())); 4018 __ Push(Smi::FromInt(strict_mode_flag()));
4068 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, safepoint_generator); 4019 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, safepoint_generator);
4069 } 4020 }
4070 4021
4071 4022
4072 void LCodeGen::DoIn(LIn* instr) { 4023 void LCodeGen::DoIn(LIn* instr) {
4073 LOperand* obj = instr->object(); 4024 LOperand* obj = instr->object();
4074 LOperand* key = instr->key(); 4025 LOperand* key = instr->key();
4075 EmitPushTaggedOperand(key); 4026 EmitPushTaggedOperand(key);
4076 EmitPushTaggedOperand(obj); 4027 EmitPushTaggedOperand(obj);
4077 ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment()); 4028 ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment());
4078 LPointerMap* pointers = instr->pointer_map(); 4029 LPointerMap* pointers = instr->pointer_map();
4079 LEnvironment* env = instr->deoptimization_environment();
4080 RecordPosition(pointers->position()); 4030 RecordPosition(pointers->position());
4081 RegisterEnvironmentForDeoptimization(env); 4031 SafepointGenerator safepoint_generator(
4082 // Create safepoint generator that will also ensure enough space in the 4032 this, pointers, Safepoint::kLazyDeopt);
4083 // reloc info for patching in deoptimization (since this is invoking a
4084 // builtin)
4085 SafepointGenerator safepoint_generator(this,
4086 pointers,
4087 env->deoptimization_index());
4088 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION, safepoint_generator); 4033 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION, safepoint_generator);
4089 } 4034 }
4090 4035
4091 4036
4092 void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) { 4037 void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) {
4093 { 4038 PushSafepointRegistersScope scope(this);
4094 PushSafepointRegistersScope scope(this); 4039 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
4095 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 4040 __ CallRuntimeSaveDoubles(Runtime::kStackGuard);
4096 __ CallRuntimeSaveDoubles(Runtime::kStackGuard); 4041 RecordSafepointWithLazyDeopt(instr, RECORD_SAFEPOINT_WITH_REGISTERS, 0);
4097 RegisterLazyDeoptimization(instr, RECORD_SAFEPOINT_WITH_REGISTERS, 0); 4042 ASSERT(instr->HasEnvironment());
4098 } 4043 LEnvironment* env = instr->environment();
4099 4044 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index());
4100 // The gap code includes the restoring of the safepoint registers.
4101 int pc = masm()->pc_offset();
4102 safepoints_.SetPcAfterGap(pc);
4103 } 4045 }
4104 4046
4105 4047
4106 void LCodeGen::DoStackCheck(LStackCheck* instr) { 4048 void LCodeGen::DoStackCheck(LStackCheck* instr) {
4107 class DeferredStackCheck: public LDeferredCode { 4049 class DeferredStackCheck: public LDeferredCode {
4108 public: 4050 public:
4109 DeferredStackCheck(LCodeGen* codegen, LStackCheck* instr) 4051 DeferredStackCheck(LCodeGen* codegen, LStackCheck* instr)
4110 : LDeferredCode(codegen), instr_(instr) { } 4052 : LDeferredCode(codegen), instr_(instr) { }
4111 virtual void Generate() { codegen()->DoDeferredStackCheck(instr_); } 4053 virtual void Generate() { codegen()->DoDeferredStackCheck(instr_); }
4112 private: 4054 private:
4113 LStackCheck* instr_; 4055 LStackCheck* instr_;
4114 }; 4056 };
4115 4057
4058 ASSERT(instr->HasEnvironment());
4059 LEnvironment* env = instr->environment();
4060 // There is no LLazyBailout instruction for stack-checks. We have to
4061 // prepare for lazy deoptimization explicitly here.
4116 if (instr->hydrogen()->is_function_entry()) { 4062 if (instr->hydrogen()->is_function_entry()) {
4117 // Perform stack overflow check. 4063 // Perform stack overflow check.
4118 Label done; 4064 Label done;
4119 __ CompareRoot(rsp, Heap::kStackLimitRootIndex); 4065 __ CompareRoot(rsp, Heap::kStackLimitRootIndex);
4120 __ j(above_equal, &done, Label::kNear); 4066 __ j(above_equal, &done, Label::kNear);
4121 StackCheckStub stub; 4067 StackCheckStub stub;
4122 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 4068 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
4069 EnsureSpaceForLazyDeopt(Deoptimizer::patch_size());
4070 last_lazy_deopt_pc_ = masm()->pc_offset();
4123 __ bind(&done); 4071 __ bind(&done);
4072 RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt);
4073 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index());
4124 } else { 4074 } else {
4125 ASSERT(instr->hydrogen()->is_backwards_branch()); 4075 ASSERT(instr->hydrogen()->is_backwards_branch());
4126 // Perform stack overflow check if this goto needs it before jumping. 4076 // Perform stack overflow check if this goto needs it before jumping.
4127 DeferredStackCheck* deferred_stack_check = 4077 DeferredStackCheck* deferred_stack_check =
4128 new DeferredStackCheck(this, instr); 4078 new DeferredStackCheck(this, instr);
4129 __ CompareRoot(rsp, Heap::kStackLimitRootIndex); 4079 __ CompareRoot(rsp, Heap::kStackLimitRootIndex);
4130 __ j(below, deferred_stack_check->entry()); 4080 __ j(below, deferred_stack_check->entry());
4081 EnsureSpaceForLazyDeopt(Deoptimizer::patch_size());
4082 last_lazy_deopt_pc_ = masm()->pc_offset();
4131 __ bind(instr->done_label()); 4083 __ bind(instr->done_label());
4132 deferred_stack_check->SetExit(instr->done_label()); 4084 deferred_stack_check->SetExit(instr->done_label());
4085 RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt);
4086 // Don't record a deoptimization index for the safepoint here.
4087 // This will be done explicitly when emitting call and the safepoint in
4088 // the deferred code.
4133 } 4089 }
4134 } 4090 }
4135 4091
4136 4092
4137 void LCodeGen::DoOsrEntry(LOsrEntry* instr) { 4093 void LCodeGen::DoOsrEntry(LOsrEntry* instr) {
4138 // This is a pseudo-instruction that ensures that the environment here is 4094 // This is a pseudo-instruction that ensures that the environment here is
4139 // properly registered for deoptimization and records the assembler's PC 4095 // properly registered for deoptimization and records the assembler's PC
4140 // offset. 4096 // offset.
4141 LEnvironment* environment = instr->environment(); 4097 LEnvironment* environment = instr->environment();
4142 environment->SetSpilledRegisters(instr->SpilledRegisterArray(), 4098 environment->SetSpilledRegisters(instr->SpilledRegisterArray(),
4143 instr->SpilledDoubleRegisterArray()); 4099 instr->SpilledDoubleRegisterArray());
4144 4100
4145 // If the environment were already registered, we would have no way of 4101 // If the environment were already registered, we would have no way of
4146 // backpatching it with the spill slot operands. 4102 // backpatching it with the spill slot operands.
4147 ASSERT(!environment->HasBeenRegistered()); 4103 ASSERT(!environment->HasBeenRegistered());
4148 RegisterEnvironmentForDeoptimization(environment); 4104 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt);
4149 ASSERT(osr_pc_offset_ == -1); 4105 ASSERT(osr_pc_offset_ == -1);
4150 osr_pc_offset_ = masm()->pc_offset(); 4106 osr_pc_offset_ = masm()->pc_offset();
4151 } 4107 }
4152 4108
4153 #undef __ 4109 #undef __
4154 4110
4155 } } // namespace v8::internal 4111 } } // namespace v8::internal
4156 4112
4157 #endif // V8_TARGET_ARCH_X64 4113 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/lithium-codegen-x64.h ('k') | test/mjsunit/compiler/regress-funcaller.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698