OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_X64 | 7 #if V8_TARGET_ARCH_X64 |
8 | 8 |
9 #include "src/code-stubs.h" | 9 #include "src/code-stubs.h" |
10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
(...skipping 13 matching lines...) Expand all Loading... |
24 | 24 |
25 class JumpPatchSite BASE_EMBEDDED { | 25 class JumpPatchSite BASE_EMBEDDED { |
26 public: | 26 public: |
27 explicit JumpPatchSite(MacroAssembler* masm) : masm_(masm) { | 27 explicit JumpPatchSite(MacroAssembler* masm) : masm_(masm) { |
28 #ifdef DEBUG | 28 #ifdef DEBUG |
29 info_emitted_ = false; | 29 info_emitted_ = false; |
30 #endif | 30 #endif |
31 } | 31 } |
32 | 32 |
33 ~JumpPatchSite() { | 33 ~JumpPatchSite() { |
34 ASSERT(patch_site_.is_bound() == info_emitted_); | 34 DCHECK(patch_site_.is_bound() == info_emitted_); |
35 } | 35 } |
36 | 36 |
37 void EmitJumpIfNotSmi(Register reg, | 37 void EmitJumpIfNotSmi(Register reg, |
38 Label* target, | 38 Label* target, |
39 Label::Distance near_jump = Label::kFar) { | 39 Label::Distance near_jump = Label::kFar) { |
40 __ testb(reg, Immediate(kSmiTagMask)); | 40 __ testb(reg, Immediate(kSmiTagMask)); |
41 EmitJump(not_carry, target, near_jump); // Always taken before patched. | 41 EmitJump(not_carry, target, near_jump); // Always taken before patched. |
42 } | 42 } |
43 | 43 |
44 void EmitJumpIfSmi(Register reg, | 44 void EmitJumpIfSmi(Register reg, |
45 Label* target, | 45 Label* target, |
46 Label::Distance near_jump = Label::kFar) { | 46 Label::Distance near_jump = Label::kFar) { |
47 __ testb(reg, Immediate(kSmiTagMask)); | 47 __ testb(reg, Immediate(kSmiTagMask)); |
48 EmitJump(carry, target, near_jump); // Never taken before patched. | 48 EmitJump(carry, target, near_jump); // Never taken before patched. |
49 } | 49 } |
50 | 50 |
51 void EmitPatchInfo() { | 51 void EmitPatchInfo() { |
52 if (patch_site_.is_bound()) { | 52 if (patch_site_.is_bound()) { |
53 int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(&patch_site_); | 53 int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(&patch_site_); |
54 ASSERT(is_uint8(delta_to_patch_site)); | 54 DCHECK(is_uint8(delta_to_patch_site)); |
55 __ testl(rax, Immediate(delta_to_patch_site)); | 55 __ testl(rax, Immediate(delta_to_patch_site)); |
56 #ifdef DEBUG | 56 #ifdef DEBUG |
57 info_emitted_ = true; | 57 info_emitted_ = true; |
58 #endif | 58 #endif |
59 } else { | 59 } else { |
60 __ nop(); // Signals no inlined code. | 60 __ nop(); // Signals no inlined code. |
61 } | 61 } |
62 } | 62 } |
63 | 63 |
64 private: | 64 private: |
65 // jc will be patched with jz, jnc will become jnz. | 65 // jc will be patched with jz, jnc will become jnz. |
66 void EmitJump(Condition cc, Label* target, Label::Distance near_jump) { | 66 void EmitJump(Condition cc, Label* target, Label::Distance near_jump) { |
67 ASSERT(!patch_site_.is_bound() && !info_emitted_); | 67 DCHECK(!patch_site_.is_bound() && !info_emitted_); |
68 ASSERT(cc == carry || cc == not_carry); | 68 DCHECK(cc == carry || cc == not_carry); |
69 __ bind(&patch_site_); | 69 __ bind(&patch_site_); |
70 __ j(cc, target, near_jump); | 70 __ j(cc, target, near_jump); |
71 } | 71 } |
72 | 72 |
73 MacroAssembler* masm_; | 73 MacroAssembler* masm_; |
74 Label patch_site_; | 74 Label patch_site_; |
75 #ifdef DEBUG | 75 #ifdef DEBUG |
76 bool info_emitted_; | 76 bool info_emitted_; |
77 #endif | 77 #endif |
78 }; | 78 }; |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
135 // the frame (that is done below). | 135 // the frame (that is done below). |
136 FrameScope frame_scope(masm_, StackFrame::MANUAL); | 136 FrameScope frame_scope(masm_, StackFrame::MANUAL); |
137 | 137 |
138 info->set_prologue_offset(masm_->pc_offset()); | 138 info->set_prologue_offset(masm_->pc_offset()); |
139 __ Prologue(info->IsCodePreAgingActive()); | 139 __ Prologue(info->IsCodePreAgingActive()); |
140 info->AddNoFrameRange(0, masm_->pc_offset()); | 140 info->AddNoFrameRange(0, masm_->pc_offset()); |
141 | 141 |
142 { Comment cmnt(masm_, "[ Allocate locals"); | 142 { Comment cmnt(masm_, "[ Allocate locals"); |
143 int locals_count = info->scope()->num_stack_slots(); | 143 int locals_count = info->scope()->num_stack_slots(); |
144 // Generators allocate locals, if any, in context slots. | 144 // Generators allocate locals, if any, in context slots. |
145 ASSERT(!info->function()->is_generator() || locals_count == 0); | 145 DCHECK(!info->function()->is_generator() || locals_count == 0); |
146 if (locals_count == 1) { | 146 if (locals_count == 1) { |
147 __ PushRoot(Heap::kUndefinedValueRootIndex); | 147 __ PushRoot(Heap::kUndefinedValueRootIndex); |
148 } else if (locals_count > 1) { | 148 } else if (locals_count > 1) { |
149 if (locals_count >= 128) { | 149 if (locals_count >= 128) { |
150 Label ok; | 150 Label ok; |
151 __ movp(rcx, rsp); | 151 __ movp(rcx, rsp); |
152 __ subp(rcx, Immediate(locals_count * kPointerSize)); | 152 __ subp(rcx, Immediate(locals_count * kPointerSize)); |
153 __ CompareRoot(rcx, Heap::kRealStackLimitRootIndex); | 153 __ CompareRoot(rcx, Heap::kRealStackLimitRootIndex); |
154 __ j(above_equal, &ok, Label::kNear); | 154 __ j(above_equal, &ok, Label::kNear); |
155 __ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION); | 155 __ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION); |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
277 Comment cmnt(masm_, "[ Declarations"); | 277 Comment cmnt(masm_, "[ Declarations"); |
278 scope()->VisitIllegalRedeclaration(this); | 278 scope()->VisitIllegalRedeclaration(this); |
279 | 279 |
280 } else { | 280 } else { |
281 PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS); | 281 PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS); |
282 { Comment cmnt(masm_, "[ Declarations"); | 282 { Comment cmnt(masm_, "[ Declarations"); |
283 // For named function expressions, declare the function name as a | 283 // For named function expressions, declare the function name as a |
284 // constant. | 284 // constant. |
285 if (scope()->is_function_scope() && scope()->function() != NULL) { | 285 if (scope()->is_function_scope() && scope()->function() != NULL) { |
286 VariableDeclaration* function = scope()->function(); | 286 VariableDeclaration* function = scope()->function(); |
287 ASSERT(function->proxy()->var()->mode() == CONST || | 287 DCHECK(function->proxy()->var()->mode() == CONST || |
288 function->proxy()->var()->mode() == CONST_LEGACY); | 288 function->proxy()->var()->mode() == CONST_LEGACY); |
289 ASSERT(function->proxy()->var()->location() != Variable::UNALLOCATED); | 289 DCHECK(function->proxy()->var()->location() != Variable::UNALLOCATED); |
290 VisitVariableDeclaration(function); | 290 VisitVariableDeclaration(function); |
291 } | 291 } |
292 VisitDeclarations(scope()->declarations()); | 292 VisitDeclarations(scope()->declarations()); |
293 } | 293 } |
294 | 294 |
295 { Comment cmnt(masm_, "[ Stack check"); | 295 { Comment cmnt(masm_, "[ Stack check"); |
296 PrepareForBailoutForId(BailoutId::Declarations(), NO_REGISTERS); | 296 PrepareForBailoutForId(BailoutId::Declarations(), NO_REGISTERS); |
297 Label ok; | 297 Label ok; |
298 __ CompareRoot(rsp, Heap::kStackLimitRootIndex); | 298 __ CompareRoot(rsp, Heap::kStackLimitRootIndex); |
299 __ j(above_equal, &ok, Label::kNear); | 299 __ j(above_equal, &ok, Label::kNear); |
300 __ call(isolate()->builtins()->StackCheck(), RelocInfo::CODE_TARGET); | 300 __ call(isolate()->builtins()->StackCheck(), RelocInfo::CODE_TARGET); |
301 __ bind(&ok); | 301 __ bind(&ok); |
302 } | 302 } |
303 | 303 |
304 { Comment cmnt(masm_, "[ Body"); | 304 { Comment cmnt(masm_, "[ Body"); |
305 ASSERT(loop_depth() == 0); | 305 DCHECK(loop_depth() == 0); |
306 VisitStatements(function()->body()); | 306 VisitStatements(function()->body()); |
307 ASSERT(loop_depth() == 0); | 307 DCHECK(loop_depth() == 0); |
308 } | 308 } |
309 } | 309 } |
310 | 310 |
311 // Always emit a 'return undefined' in case control fell off the end of | 311 // Always emit a 'return undefined' in case control fell off the end of |
312 // the body. | 312 // the body. |
313 { Comment cmnt(masm_, "[ return <undefined>;"); | 313 { Comment cmnt(masm_, "[ return <undefined>;"); |
314 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); | 314 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); |
315 EmitReturnSequence(); | 315 EmitReturnSequence(); |
316 } | 316 } |
317 } | 317 } |
(...skipping 20 matching lines...) Expand all Loading... |
338 | 338 |
339 | 339 |
340 static const byte kJnsOffset = kPointerSize == kInt64Size ? 0x1d : 0x14; | 340 static const byte kJnsOffset = kPointerSize == kInt64Size ? 0x1d : 0x14; |
341 | 341 |
342 | 342 |
343 void FullCodeGenerator::EmitBackEdgeBookkeeping(IterationStatement* stmt, | 343 void FullCodeGenerator::EmitBackEdgeBookkeeping(IterationStatement* stmt, |
344 Label* back_edge_target) { | 344 Label* back_edge_target) { |
345 Comment cmnt(masm_, "[ Back edge bookkeeping"); | 345 Comment cmnt(masm_, "[ Back edge bookkeeping"); |
346 Label ok; | 346 Label ok; |
347 | 347 |
348 ASSERT(back_edge_target->is_bound()); | 348 DCHECK(back_edge_target->is_bound()); |
349 int distance = masm_->SizeOfCodeGeneratedSince(back_edge_target); | 349 int distance = masm_->SizeOfCodeGeneratedSince(back_edge_target); |
350 int weight = Min(kMaxBackEdgeWeight, | 350 int weight = Min(kMaxBackEdgeWeight, |
351 Max(1, distance / kCodeSizeMultiplier)); | 351 Max(1, distance / kCodeSizeMultiplier)); |
352 EmitProfilingCounterDecrement(weight); | 352 EmitProfilingCounterDecrement(weight); |
353 | 353 |
354 __ j(positive, &ok, Label::kNear); | 354 __ j(positive, &ok, Label::kNear); |
355 { | 355 { |
356 PredictableCodeSizeScope predictible_code_size_scope(masm_, kJnsOffset); | 356 PredictableCodeSizeScope predictible_code_size_scope(masm_, kJnsOffset); |
357 DontEmitDebugCodeScope dont_emit_debug_code_scope(masm_); | 357 DontEmitDebugCodeScope dont_emit_debug_code_scope(masm_); |
358 __ call(isolate()->builtins()->InterruptCheck(), RelocInfo::CODE_TARGET); | 358 __ call(isolate()->builtins()->InterruptCheck(), RelocInfo::CODE_TARGET); |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
421 // Add padding that will be overwritten by a debugger breakpoint. We | 421 // Add padding that will be overwritten by a debugger breakpoint. We |
422 // have just generated at least 7 bytes: "movp rsp, rbp; pop rbp; ret k" | 422 // have just generated at least 7 bytes: "movp rsp, rbp; pop rbp; ret k" |
423 // (3 + 1 + 3) for x64 and at least 6 (2 + 1 + 3) bytes for x32. | 423 // (3 + 1 + 3) for x64 and at least 6 (2 + 1 + 3) bytes for x32. |
424 const int kPadding = Assembler::kJSReturnSequenceLength - | 424 const int kPadding = Assembler::kJSReturnSequenceLength - |
425 kPointerSize == kInt64Size ? 7 : 6; | 425 kPointerSize == kInt64Size ? 7 : 6; |
426 for (int i = 0; i < kPadding; ++i) { | 426 for (int i = 0; i < kPadding; ++i) { |
427 masm_->int3(); | 427 masm_->int3(); |
428 } | 428 } |
429 // Check that the size of the code used for returning is large enough | 429 // Check that the size of the code used for returning is large enough |
430 // for the debugger's requirements. | 430 // for the debugger's requirements. |
431 ASSERT(Assembler::kJSReturnSequenceLength <= | 431 DCHECK(Assembler::kJSReturnSequenceLength <= |
432 masm_->SizeOfCodeGeneratedSince(&check_exit_codesize)); | 432 masm_->SizeOfCodeGeneratedSince(&check_exit_codesize)); |
433 | 433 |
434 info_->AddNoFrameRange(no_frame_start, masm_->pc_offset()); | 434 info_->AddNoFrameRange(no_frame_start, masm_->pc_offset()); |
435 } | 435 } |
436 } | 436 } |
437 | 437 |
438 | 438 |
439 void FullCodeGenerator::EffectContext::Plug(Variable* var) const { | 439 void FullCodeGenerator::EffectContext::Plug(Variable* var) const { |
440 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); | 440 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
441 } | 441 } |
442 | 442 |
443 | 443 |
444 void FullCodeGenerator::AccumulatorValueContext::Plug(Variable* var) const { | 444 void FullCodeGenerator::AccumulatorValueContext::Plug(Variable* var) const { |
445 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); | 445 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
446 codegen()->GetVar(result_register(), var); | 446 codegen()->GetVar(result_register(), var); |
447 } | 447 } |
448 | 448 |
449 | 449 |
450 void FullCodeGenerator::StackValueContext::Plug(Variable* var) const { | 450 void FullCodeGenerator::StackValueContext::Plug(Variable* var) const { |
451 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); | 451 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
452 MemOperand operand = codegen()->VarOperand(var, result_register()); | 452 MemOperand operand = codegen()->VarOperand(var, result_register()); |
453 __ Push(operand); | 453 __ Push(operand); |
454 } | 454 } |
455 | 455 |
456 | 456 |
457 void FullCodeGenerator::TestContext::Plug(Variable* var) const { | 457 void FullCodeGenerator::TestContext::Plug(Variable* var) const { |
458 codegen()->GetVar(result_register(), var); | 458 codegen()->GetVar(result_register(), var); |
459 codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL); | 459 codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL); |
460 codegen()->DoTest(this); | 460 codegen()->DoTest(this); |
461 } | 461 } |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
516 __ Push(lit); | 516 __ Push(lit); |
517 } | 517 } |
518 } | 518 } |
519 | 519 |
520 | 520 |
521 void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const { | 521 void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const { |
522 codegen()->PrepareForBailoutBeforeSplit(condition(), | 522 codegen()->PrepareForBailoutBeforeSplit(condition(), |
523 true, | 523 true, |
524 true_label_, | 524 true_label_, |
525 false_label_); | 525 false_label_); |
526 ASSERT(!lit->IsUndetectableObject()); // There are no undetectable literals. | 526 DCHECK(!lit->IsUndetectableObject()); // There are no undetectable literals. |
527 if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) { | 527 if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) { |
528 if (false_label_ != fall_through_) __ jmp(false_label_); | 528 if (false_label_ != fall_through_) __ jmp(false_label_); |
529 } else if (lit->IsTrue() || lit->IsJSObject()) { | 529 } else if (lit->IsTrue() || lit->IsJSObject()) { |
530 if (true_label_ != fall_through_) __ jmp(true_label_); | 530 if (true_label_ != fall_through_) __ jmp(true_label_); |
531 } else if (lit->IsString()) { | 531 } else if (lit->IsString()) { |
532 if (String::cast(*lit)->length() == 0) { | 532 if (String::cast(*lit)->length() == 0) { |
533 if (false_label_ != fall_through_) __ jmp(false_label_); | 533 if (false_label_ != fall_through_) __ jmp(false_label_); |
534 } else { | 534 } else { |
535 if (true_label_ != fall_through_) __ jmp(true_label_); | 535 if (true_label_ != fall_through_) __ jmp(true_label_); |
536 } | 536 } |
537 } else if (lit->IsSmi()) { | 537 } else if (lit->IsSmi()) { |
538 if (Smi::cast(*lit)->value() == 0) { | 538 if (Smi::cast(*lit)->value() == 0) { |
539 if (false_label_ != fall_through_) __ jmp(false_label_); | 539 if (false_label_ != fall_through_) __ jmp(false_label_); |
540 } else { | 540 } else { |
541 if (true_label_ != fall_through_) __ jmp(true_label_); | 541 if (true_label_ != fall_through_) __ jmp(true_label_); |
542 } | 542 } |
543 } else { | 543 } else { |
544 // For simplicity we always test the accumulator register. | 544 // For simplicity we always test the accumulator register. |
545 __ Move(result_register(), lit); | 545 __ Move(result_register(), lit); |
546 codegen()->DoTest(this); | 546 codegen()->DoTest(this); |
547 } | 547 } |
548 } | 548 } |
549 | 549 |
550 | 550 |
551 void FullCodeGenerator::EffectContext::DropAndPlug(int count, | 551 void FullCodeGenerator::EffectContext::DropAndPlug(int count, |
552 Register reg) const { | 552 Register reg) const { |
553 ASSERT(count > 0); | 553 DCHECK(count > 0); |
554 __ Drop(count); | 554 __ Drop(count); |
555 } | 555 } |
556 | 556 |
557 | 557 |
558 void FullCodeGenerator::AccumulatorValueContext::DropAndPlug( | 558 void FullCodeGenerator::AccumulatorValueContext::DropAndPlug( |
559 int count, | 559 int count, |
560 Register reg) const { | 560 Register reg) const { |
561 ASSERT(count > 0); | 561 DCHECK(count > 0); |
562 __ Drop(count); | 562 __ Drop(count); |
563 __ Move(result_register(), reg); | 563 __ Move(result_register(), reg); |
564 } | 564 } |
565 | 565 |
566 | 566 |
567 void FullCodeGenerator::StackValueContext::DropAndPlug(int count, | 567 void FullCodeGenerator::StackValueContext::DropAndPlug(int count, |
568 Register reg) const { | 568 Register reg) const { |
569 ASSERT(count > 0); | 569 DCHECK(count > 0); |
570 if (count > 1) __ Drop(count - 1); | 570 if (count > 1) __ Drop(count - 1); |
571 __ movp(Operand(rsp, 0), reg); | 571 __ movp(Operand(rsp, 0), reg); |
572 } | 572 } |
573 | 573 |
574 | 574 |
575 void FullCodeGenerator::TestContext::DropAndPlug(int count, | 575 void FullCodeGenerator::TestContext::DropAndPlug(int count, |
576 Register reg) const { | 576 Register reg) const { |
577 ASSERT(count > 0); | 577 DCHECK(count > 0); |
578 // For simplicity we always test the accumulator register. | 578 // For simplicity we always test the accumulator register. |
579 __ Drop(count); | 579 __ Drop(count); |
580 __ Move(result_register(), reg); | 580 __ Move(result_register(), reg); |
581 codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL); | 581 codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL); |
582 codegen()->DoTest(this); | 582 codegen()->DoTest(this); |
583 } | 583 } |
584 | 584 |
585 | 585 |
586 void FullCodeGenerator::EffectContext::Plug(Label* materialize_true, | 586 void FullCodeGenerator::EffectContext::Plug(Label* materialize_true, |
587 Label* materialize_false) const { | 587 Label* materialize_false) const { |
588 ASSERT(materialize_true == materialize_false); | 588 DCHECK(materialize_true == materialize_false); |
589 __ bind(materialize_true); | 589 __ bind(materialize_true); |
590 } | 590 } |
591 | 591 |
592 | 592 |
593 void FullCodeGenerator::AccumulatorValueContext::Plug( | 593 void FullCodeGenerator::AccumulatorValueContext::Plug( |
594 Label* materialize_true, | 594 Label* materialize_true, |
595 Label* materialize_false) const { | 595 Label* materialize_false) const { |
596 Label done; | 596 Label done; |
597 __ bind(materialize_true); | 597 __ bind(materialize_true); |
598 __ Move(result_register(), isolate()->factory()->true_value()); | 598 __ Move(result_register(), isolate()->factory()->true_value()); |
(...skipping 12 matching lines...) Expand all Loading... |
611 __ Push(isolate()->factory()->true_value()); | 611 __ Push(isolate()->factory()->true_value()); |
612 __ jmp(&done, Label::kNear); | 612 __ jmp(&done, Label::kNear); |
613 __ bind(materialize_false); | 613 __ bind(materialize_false); |
614 __ Push(isolate()->factory()->false_value()); | 614 __ Push(isolate()->factory()->false_value()); |
615 __ bind(&done); | 615 __ bind(&done); |
616 } | 616 } |
617 | 617 |
618 | 618 |
619 void FullCodeGenerator::TestContext::Plug(Label* materialize_true, | 619 void FullCodeGenerator::TestContext::Plug(Label* materialize_true, |
620 Label* materialize_false) const { | 620 Label* materialize_false) const { |
621 ASSERT(materialize_true == true_label_); | 621 DCHECK(materialize_true == true_label_); |
622 ASSERT(materialize_false == false_label_); | 622 DCHECK(materialize_false == false_label_); |
623 } | 623 } |
624 | 624 |
625 | 625 |
626 void FullCodeGenerator::EffectContext::Plug(bool flag) const { | 626 void FullCodeGenerator::EffectContext::Plug(bool flag) const { |
627 } | 627 } |
628 | 628 |
629 | 629 |
630 void FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const { | 630 void FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const { |
631 Heap::RootListIndex value_root_index = | 631 Heap::RootListIndex value_root_index = |
632 flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex; | 632 flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex; |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
675 } else if (if_true == fall_through) { | 675 } else if (if_true == fall_through) { |
676 __ j(NegateCondition(cc), if_false); | 676 __ j(NegateCondition(cc), if_false); |
677 } else { | 677 } else { |
678 __ j(cc, if_true); | 678 __ j(cc, if_true); |
679 __ jmp(if_false); | 679 __ jmp(if_false); |
680 } | 680 } |
681 } | 681 } |
682 | 682 |
683 | 683 |
684 MemOperand FullCodeGenerator::StackOperand(Variable* var) { | 684 MemOperand FullCodeGenerator::StackOperand(Variable* var) { |
685 ASSERT(var->IsStackAllocated()); | 685 DCHECK(var->IsStackAllocated()); |
686 // Offset is negative because higher indexes are at lower addresses. | 686 // Offset is negative because higher indexes are at lower addresses. |
687 int offset = -var->index() * kPointerSize; | 687 int offset = -var->index() * kPointerSize; |
688 // Adjust by a (parameter or local) base offset. | 688 // Adjust by a (parameter or local) base offset. |
689 if (var->IsParameter()) { | 689 if (var->IsParameter()) { |
690 offset += kFPOnStackSize + kPCOnStackSize + | 690 offset += kFPOnStackSize + kPCOnStackSize + |
691 (info_->scope()->num_parameters() - 1) * kPointerSize; | 691 (info_->scope()->num_parameters() - 1) * kPointerSize; |
692 } else { | 692 } else { |
693 offset += JavaScriptFrameConstants::kLocal0Offset; | 693 offset += JavaScriptFrameConstants::kLocal0Offset; |
694 } | 694 } |
695 return Operand(rbp, offset); | 695 return Operand(rbp, offset); |
696 } | 696 } |
697 | 697 |
698 | 698 |
699 MemOperand FullCodeGenerator::VarOperand(Variable* var, Register scratch) { | 699 MemOperand FullCodeGenerator::VarOperand(Variable* var, Register scratch) { |
700 ASSERT(var->IsContextSlot() || var->IsStackAllocated()); | 700 DCHECK(var->IsContextSlot() || var->IsStackAllocated()); |
701 if (var->IsContextSlot()) { | 701 if (var->IsContextSlot()) { |
702 int context_chain_length = scope()->ContextChainLength(var->scope()); | 702 int context_chain_length = scope()->ContextChainLength(var->scope()); |
703 __ LoadContext(scratch, context_chain_length); | 703 __ LoadContext(scratch, context_chain_length); |
704 return ContextOperand(scratch, var->index()); | 704 return ContextOperand(scratch, var->index()); |
705 } else { | 705 } else { |
706 return StackOperand(var); | 706 return StackOperand(var); |
707 } | 707 } |
708 } | 708 } |
709 | 709 |
710 | 710 |
711 void FullCodeGenerator::GetVar(Register dest, Variable* var) { | 711 void FullCodeGenerator::GetVar(Register dest, Variable* var) { |
712 ASSERT(var->IsContextSlot() || var->IsStackAllocated()); | 712 DCHECK(var->IsContextSlot() || var->IsStackAllocated()); |
713 MemOperand location = VarOperand(var, dest); | 713 MemOperand location = VarOperand(var, dest); |
714 __ movp(dest, location); | 714 __ movp(dest, location); |
715 } | 715 } |
716 | 716 |
717 | 717 |
718 void FullCodeGenerator::SetVar(Variable* var, | 718 void FullCodeGenerator::SetVar(Variable* var, |
719 Register src, | 719 Register src, |
720 Register scratch0, | 720 Register scratch0, |
721 Register scratch1) { | 721 Register scratch1) { |
722 ASSERT(var->IsContextSlot() || var->IsStackAllocated()); | 722 DCHECK(var->IsContextSlot() || var->IsStackAllocated()); |
723 ASSERT(!scratch0.is(src)); | 723 DCHECK(!scratch0.is(src)); |
724 ASSERT(!scratch0.is(scratch1)); | 724 DCHECK(!scratch0.is(scratch1)); |
725 ASSERT(!scratch1.is(src)); | 725 DCHECK(!scratch1.is(src)); |
726 MemOperand location = VarOperand(var, scratch0); | 726 MemOperand location = VarOperand(var, scratch0); |
727 __ movp(location, src); | 727 __ movp(location, src); |
728 | 728 |
729 // Emit the write barrier code if the location is in the heap. | 729 // Emit the write barrier code if the location is in the heap. |
730 if (var->IsContextSlot()) { | 730 if (var->IsContextSlot()) { |
731 int offset = Context::SlotOffset(var->index()); | 731 int offset = Context::SlotOffset(var->index()); |
732 __ RecordWriteContextSlot(scratch0, offset, src, scratch1, kDontSaveFPRegs); | 732 __ RecordWriteContextSlot(scratch0, offset, src, scratch1, kDontSaveFPRegs); |
733 } | 733 } |
734 } | 734 } |
735 | 735 |
(...skipping 13 matching lines...) Expand all Loading... |
749 if (should_normalize) { | 749 if (should_normalize) { |
750 __ CompareRoot(rax, Heap::kTrueValueRootIndex); | 750 __ CompareRoot(rax, Heap::kTrueValueRootIndex); |
751 Split(equal, if_true, if_false, NULL); | 751 Split(equal, if_true, if_false, NULL); |
752 __ bind(&skip); | 752 __ bind(&skip); |
753 } | 753 } |
754 } | 754 } |
755 | 755 |
756 | 756 |
757 void FullCodeGenerator::EmitDebugCheckDeclarationContext(Variable* variable) { | 757 void FullCodeGenerator::EmitDebugCheckDeclarationContext(Variable* variable) { |
758 // The variable in the declaration always resides in the current context. | 758 // The variable in the declaration always resides in the current context. |
759 ASSERT_EQ(0, scope()->ContextChainLength(variable->scope())); | 759 DCHECK_EQ(0, scope()->ContextChainLength(variable->scope())); |
760 if (generate_debug_code_) { | 760 if (generate_debug_code_) { |
761 // Check that we're not inside a with or catch context. | 761 // Check that we're not inside a with or catch context. |
762 __ movp(rbx, FieldOperand(rsi, HeapObject::kMapOffset)); | 762 __ movp(rbx, FieldOperand(rsi, HeapObject::kMapOffset)); |
763 __ CompareRoot(rbx, Heap::kWithContextMapRootIndex); | 763 __ CompareRoot(rbx, Heap::kWithContextMapRootIndex); |
764 __ Check(not_equal, kDeclarationInWithContext); | 764 __ Check(not_equal, kDeclarationInWithContext); |
765 __ CompareRoot(rbx, Heap::kCatchContextMapRootIndex); | 765 __ CompareRoot(rbx, Heap::kCatchContextMapRootIndex); |
766 __ Check(not_equal, kDeclarationInCatchContext); | 766 __ Check(not_equal, kDeclarationInCatchContext); |
767 } | 767 } |
768 } | 768 } |
769 | 769 |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
804 // No write barrier since the hole value is in old space. | 804 // No write barrier since the hole value is in old space. |
805 PrepareForBailoutForId(proxy->id(), NO_REGISTERS); | 805 PrepareForBailoutForId(proxy->id(), NO_REGISTERS); |
806 } | 806 } |
807 break; | 807 break; |
808 | 808 |
809 case Variable::LOOKUP: { | 809 case Variable::LOOKUP: { |
810 Comment cmnt(masm_, "[ VariableDeclaration"); | 810 Comment cmnt(masm_, "[ VariableDeclaration"); |
811 __ Push(rsi); | 811 __ Push(rsi); |
812 __ Push(variable->name()); | 812 __ Push(variable->name()); |
813 // Declaration nodes are always introduced in one of four modes. | 813 // Declaration nodes are always introduced in one of four modes. |
814 ASSERT(IsDeclaredVariableMode(mode)); | 814 DCHECK(IsDeclaredVariableMode(mode)); |
815 PropertyAttributes attr = | 815 PropertyAttributes attr = |
816 IsImmutableVariableMode(mode) ? READ_ONLY : NONE; | 816 IsImmutableVariableMode(mode) ? READ_ONLY : NONE; |
817 __ Push(Smi::FromInt(attr)); | 817 __ Push(Smi::FromInt(attr)); |
818 // Push initial value, if any. | 818 // Push initial value, if any. |
819 // Note: For variables we must not push an initial value (such as | 819 // Note: For variables we must not push an initial value (such as |
820 // 'undefined') because we may have a (legal) redeclaration and we | 820 // 'undefined') because we may have a (legal) redeclaration and we |
821 // must not destroy the current value. | 821 // must not destroy the current value. |
822 if (hole_init) { | 822 if (hole_init) { |
823 __ PushRoot(Heap::kTheHoleValueRootIndex); | 823 __ PushRoot(Heap::kTheHoleValueRootIndex); |
824 } else { | 824 } else { |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
880 VisitForStackValue(declaration->fun()); | 880 VisitForStackValue(declaration->fun()); |
881 __ CallRuntime(Runtime::kDeclareLookupSlot, 4); | 881 __ CallRuntime(Runtime::kDeclareLookupSlot, 4); |
882 break; | 882 break; |
883 } | 883 } |
884 } | 884 } |
885 } | 885 } |
886 | 886 |
887 | 887 |
888 void FullCodeGenerator::VisitModuleDeclaration(ModuleDeclaration* declaration) { | 888 void FullCodeGenerator::VisitModuleDeclaration(ModuleDeclaration* declaration) { |
889 Variable* variable = declaration->proxy()->var(); | 889 Variable* variable = declaration->proxy()->var(); |
890 ASSERT(variable->location() == Variable::CONTEXT); | 890 DCHECK(variable->location() == Variable::CONTEXT); |
891 ASSERT(variable->interface()->IsFrozen()); | 891 DCHECK(variable->interface()->IsFrozen()); |
892 | 892 |
893 Comment cmnt(masm_, "[ ModuleDeclaration"); | 893 Comment cmnt(masm_, "[ ModuleDeclaration"); |
894 EmitDebugCheckDeclarationContext(variable); | 894 EmitDebugCheckDeclarationContext(variable); |
895 | 895 |
896 // Load instance object. | 896 // Load instance object. |
897 __ LoadContext(rax, scope_->ContextChainLength(scope_->GlobalScope())); | 897 __ LoadContext(rax, scope_->ContextChainLength(scope_->GlobalScope())); |
898 __ movp(rax, ContextOperand(rax, variable->interface()->Index())); | 898 __ movp(rax, ContextOperand(rax, variable->interface()->Index())); |
899 __ movp(rax, ContextOperand(rax, Context::EXTENSION_INDEX)); | 899 __ movp(rax, ContextOperand(rax, Context::EXTENSION_INDEX)); |
900 | 900 |
901 // Assign it. | 901 // Assign it. |
(...skipping 470 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1372 | 1372 |
1373 ContextualMode mode = (typeof_state == INSIDE_TYPEOF) | 1373 ContextualMode mode = (typeof_state == INSIDE_TYPEOF) |
1374 ? NOT_CONTEXTUAL | 1374 ? NOT_CONTEXTUAL |
1375 : CONTEXTUAL; | 1375 : CONTEXTUAL; |
1376 CallLoadIC(mode); | 1376 CallLoadIC(mode); |
1377 } | 1377 } |
1378 | 1378 |
1379 | 1379 |
1380 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, | 1380 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, |
1381 Label* slow) { | 1381 Label* slow) { |
1382 ASSERT(var->IsContextSlot()); | 1382 DCHECK(var->IsContextSlot()); |
1383 Register context = rsi; | 1383 Register context = rsi; |
1384 Register temp = rbx; | 1384 Register temp = rbx; |
1385 | 1385 |
1386 for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) { | 1386 for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) { |
1387 if (s->num_heap_slots() > 0) { | 1387 if (s->num_heap_slots() > 0) { |
1388 if (s->calls_sloppy_eval()) { | 1388 if (s->calls_sloppy_eval()) { |
1389 // Check that extension is NULL. | 1389 // Check that extension is NULL. |
1390 __ cmpp(ContextOperand(context, Context::EXTENSION_INDEX), | 1390 __ cmpp(ContextOperand(context, Context::EXTENSION_INDEX), |
1391 Immediate(0)); | 1391 Immediate(0)); |
1392 __ j(not_equal, slow); | 1392 __ j(not_equal, slow); |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1464 case Variable::LOCAL: | 1464 case Variable::LOCAL: |
1465 case Variable::CONTEXT: { | 1465 case Variable::CONTEXT: { |
1466 Comment cmnt(masm_, var->IsContextSlot() ? "[ Context slot" | 1466 Comment cmnt(masm_, var->IsContextSlot() ? "[ Context slot" |
1467 : "[ Stack slot"); | 1467 : "[ Stack slot"); |
1468 if (var->binding_needs_init()) { | 1468 if (var->binding_needs_init()) { |
1469 // var->scope() may be NULL when the proxy is located in eval code and | 1469 // var->scope() may be NULL when the proxy is located in eval code and |
1470 // refers to a potential outside binding. Currently those bindings are | 1470 // refers to a potential outside binding. Currently those bindings are |
1471 // always looked up dynamically, i.e. in that case | 1471 // always looked up dynamically, i.e. in that case |
1472 // var->location() == LOOKUP. | 1472 // var->location() == LOOKUP. |
1473 // always holds. | 1473 // always holds. |
1474 ASSERT(var->scope() != NULL); | 1474 DCHECK(var->scope() != NULL); |
1475 | 1475 |
1476 // Check if the binding really needs an initialization check. The check | 1476 // Check if the binding really needs an initialization check. The check |
1477 // can be skipped in the following situation: we have a LET or CONST | 1477 // can be skipped in the following situation: we have a LET or CONST |
1478 // binding in harmony mode, both the Variable and the VariableProxy have | 1478 // binding in harmony mode, both the Variable and the VariableProxy have |
1479 // the same declaration scope (i.e. they are both in global code, in the | 1479 // the same declaration scope (i.e. they are both in global code, in the |
1480 // same function or in the same eval code) and the VariableProxy is in | 1480 // same function or in the same eval code) and the VariableProxy is in |
1481 // the source physically located after the initializer of the variable. | 1481 // the source physically located after the initializer of the variable. |
1482 // | 1482 // |
1483 // We cannot skip any initialization checks for CONST in non-harmony | 1483 // We cannot skip any initialization checks for CONST in non-harmony |
1484 // mode because const variables may be declared but never initialized: | 1484 // mode because const variables may be declared but never initialized: |
1485 // if (false) { const x; }; var y = x; | 1485 // if (false) { const x; }; var y = x; |
1486 // | 1486 // |
1487 // The condition on the declaration scopes is a conservative check for | 1487 // The condition on the declaration scopes is a conservative check for |
1488 // nested functions that access a binding and are called before the | 1488 // nested functions that access a binding and are called before the |
1489 // binding is initialized: | 1489 // binding is initialized: |
1490 // function() { f(); let x = 1; function f() { x = 2; } } | 1490 // function() { f(); let x = 1; function f() { x = 2; } } |
1491 // | 1491 // |
1492 bool skip_init_check; | 1492 bool skip_init_check; |
1493 if (var->scope()->DeclarationScope() != scope()->DeclarationScope()) { | 1493 if (var->scope()->DeclarationScope() != scope()->DeclarationScope()) { |
1494 skip_init_check = false; | 1494 skip_init_check = false; |
1495 } else { | 1495 } else { |
1496 // Check that we always have valid source position. | 1496 // Check that we always have valid source position. |
1497 ASSERT(var->initializer_position() != RelocInfo::kNoPosition); | 1497 DCHECK(var->initializer_position() != RelocInfo::kNoPosition); |
1498 ASSERT(proxy->position() != RelocInfo::kNoPosition); | 1498 DCHECK(proxy->position() != RelocInfo::kNoPosition); |
1499 skip_init_check = var->mode() != CONST_LEGACY && | 1499 skip_init_check = var->mode() != CONST_LEGACY && |
1500 var->initializer_position() < proxy->position(); | 1500 var->initializer_position() < proxy->position(); |
1501 } | 1501 } |
1502 | 1502 |
1503 if (!skip_init_check) { | 1503 if (!skip_init_check) { |
1504 // Let and const need a read barrier. | 1504 // Let and const need a read barrier. |
1505 Label done; | 1505 Label done; |
1506 GetVar(rax, var); | 1506 GetVar(rax, var); |
1507 __ CompareRoot(rax, Heap::kTheHoleValueRootIndex); | 1507 __ CompareRoot(rax, Heap::kTheHoleValueRootIndex); |
1508 __ j(not_equal, &done, Label::kNear); | 1508 __ j(not_equal, &done, Label::kNear); |
1509 if (var->mode() == LET || var->mode() == CONST) { | 1509 if (var->mode() == LET || var->mode() == CONST) { |
1510 // Throw a reference error when using an uninitialized let/const | 1510 // Throw a reference error when using an uninitialized let/const |
1511 // binding in harmony mode. | 1511 // binding in harmony mode. |
1512 __ Push(var->name()); | 1512 __ Push(var->name()); |
1513 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 1513 __ CallRuntime(Runtime::kThrowReferenceError, 1); |
1514 } else { | 1514 } else { |
1515 // Uninitalized const bindings outside of harmony mode are unholed. | 1515 // Uninitalized const bindings outside of harmony mode are unholed. |
1516 ASSERT(var->mode() == CONST_LEGACY); | 1516 DCHECK(var->mode() == CONST_LEGACY); |
1517 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); | 1517 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); |
1518 } | 1518 } |
1519 __ bind(&done); | 1519 __ bind(&done); |
1520 context()->Plug(rax); | 1520 context()->Plug(rax); |
1521 break; | 1521 break; |
1522 } | 1522 } |
1523 } | 1523 } |
1524 context()->Plug(var); | 1524 context()->Plug(var); |
1525 break; | 1525 break; |
1526 } | 1526 } |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1654 Literal* key = property->key(); | 1654 Literal* key = property->key(); |
1655 Expression* value = property->value(); | 1655 Expression* value = property->value(); |
1656 if (!result_saved) { | 1656 if (!result_saved) { |
1657 __ Push(rax); // Save result on the stack | 1657 __ Push(rax); // Save result on the stack |
1658 result_saved = true; | 1658 result_saved = true; |
1659 } | 1659 } |
1660 switch (property->kind()) { | 1660 switch (property->kind()) { |
1661 case ObjectLiteral::Property::CONSTANT: | 1661 case ObjectLiteral::Property::CONSTANT: |
1662 UNREACHABLE(); | 1662 UNREACHABLE(); |
1663 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | 1663 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
1664 ASSERT(!CompileTimeValue::IsCompileTimeValue(value)); | 1664 DCHECK(!CompileTimeValue::IsCompileTimeValue(value)); |
1665 // Fall through. | 1665 // Fall through. |
1666 case ObjectLiteral::Property::COMPUTED: | 1666 case ObjectLiteral::Property::COMPUTED: |
1667 if (key->value()->IsInternalizedString()) { | 1667 if (key->value()->IsInternalizedString()) { |
1668 if (property->emit_store()) { | 1668 if (property->emit_store()) { |
1669 VisitForAccumulatorValue(value); | 1669 VisitForAccumulatorValue(value); |
1670 ASSERT(StoreIC::ValueRegister().is(rax)); | 1670 DCHECK(StoreIC::ValueRegister().is(rax)); |
1671 __ Move(StoreIC::NameRegister(), key->value()); | 1671 __ Move(StoreIC::NameRegister(), key->value()); |
1672 __ movp(StoreIC::ReceiverRegister(), Operand(rsp, 0)); | 1672 __ movp(StoreIC::ReceiverRegister(), Operand(rsp, 0)); |
1673 CallStoreIC(key->LiteralFeedbackId()); | 1673 CallStoreIC(key->LiteralFeedbackId()); |
1674 PrepareForBailoutForId(key->id(), NO_REGISTERS); | 1674 PrepareForBailoutForId(key->id(), NO_REGISTERS); |
1675 } else { | 1675 } else { |
1676 VisitForEffect(value); | 1676 VisitForEffect(value); |
1677 } | 1677 } |
1678 break; | 1678 break; |
1679 } | 1679 } |
1680 __ Push(Operand(rsp, 0)); // Duplicate receiver. | 1680 __ Push(Operand(rsp, 0)); // Duplicate receiver. |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1712 ++it) { | 1712 ++it) { |
1713 __ Push(Operand(rsp, 0)); // Duplicate receiver. | 1713 __ Push(Operand(rsp, 0)); // Duplicate receiver. |
1714 VisitForStackValue(it->first); | 1714 VisitForStackValue(it->first); |
1715 EmitAccessor(it->second->getter); | 1715 EmitAccessor(it->second->getter); |
1716 EmitAccessor(it->second->setter); | 1716 EmitAccessor(it->second->setter); |
1717 __ Push(Smi::FromInt(NONE)); | 1717 __ Push(Smi::FromInt(NONE)); |
1718 __ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5); | 1718 __ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5); |
1719 } | 1719 } |
1720 | 1720 |
1721 if (expr->has_function()) { | 1721 if (expr->has_function()) { |
1722 ASSERT(result_saved); | 1722 DCHECK(result_saved); |
1723 __ Push(Operand(rsp, 0)); | 1723 __ Push(Operand(rsp, 0)); |
1724 __ CallRuntime(Runtime::kToFastProperties, 1); | 1724 __ CallRuntime(Runtime::kToFastProperties, 1); |
1725 } | 1725 } |
1726 | 1726 |
1727 if (result_saved) { | 1727 if (result_saved) { |
1728 context()->PlugTOS(); | 1728 context()->PlugTOS(); |
1729 } else { | 1729 } else { |
1730 context()->Plug(rax); | 1730 context()->Plug(rax); |
1731 } | 1731 } |
1732 } | 1732 } |
1733 | 1733 |
1734 | 1734 |
1735 void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { | 1735 void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { |
1736 Comment cmnt(masm_, "[ ArrayLiteral"); | 1736 Comment cmnt(masm_, "[ ArrayLiteral"); |
1737 | 1737 |
1738 expr->BuildConstantElements(isolate()); | 1738 expr->BuildConstantElements(isolate()); |
1739 int flags = expr->depth() == 1 | 1739 int flags = expr->depth() == 1 |
1740 ? ArrayLiteral::kShallowElements | 1740 ? ArrayLiteral::kShallowElements |
1741 : ArrayLiteral::kNoFlags; | 1741 : ArrayLiteral::kNoFlags; |
1742 | 1742 |
1743 ZoneList<Expression*>* subexprs = expr->values(); | 1743 ZoneList<Expression*>* subexprs = expr->values(); |
1744 int length = subexprs->length(); | 1744 int length = subexprs->length(); |
1745 Handle<FixedArray> constant_elements = expr->constant_elements(); | 1745 Handle<FixedArray> constant_elements = expr->constant_elements(); |
1746 ASSERT_EQ(2, constant_elements->length()); | 1746 DCHECK_EQ(2, constant_elements->length()); |
1747 ElementsKind constant_elements_kind = | 1747 ElementsKind constant_elements_kind = |
1748 static_cast<ElementsKind>(Smi::cast(constant_elements->get(0))->value()); | 1748 static_cast<ElementsKind>(Smi::cast(constant_elements->get(0))->value()); |
1749 bool has_constant_fast_elements = | 1749 bool has_constant_fast_elements = |
1750 IsFastObjectElementsKind(constant_elements_kind); | 1750 IsFastObjectElementsKind(constant_elements_kind); |
1751 Handle<FixedArrayBase> constant_elements_values( | 1751 Handle<FixedArrayBase> constant_elements_values( |
1752 FixedArrayBase::cast(constant_elements->get(1))); | 1752 FixedArrayBase::cast(constant_elements->get(1))); |
1753 | 1753 |
1754 AllocationSiteMode allocation_site_mode = TRACK_ALLOCATION_SITE; | 1754 AllocationSiteMode allocation_site_mode = TRACK_ALLOCATION_SITE; |
1755 if (has_constant_fast_elements && !FLAG_allocation_site_pretenuring) { | 1755 if (has_constant_fast_elements && !FLAG_allocation_site_pretenuring) { |
1756 // If the only customer of allocation sites is transitioning, then | 1756 // If the only customer of allocation sites is transitioning, then |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1817 if (result_saved) { | 1817 if (result_saved) { |
1818 __ addp(rsp, Immediate(kPointerSize)); // literal index | 1818 __ addp(rsp, Immediate(kPointerSize)); // literal index |
1819 context()->PlugTOS(); | 1819 context()->PlugTOS(); |
1820 } else { | 1820 } else { |
1821 context()->Plug(rax); | 1821 context()->Plug(rax); |
1822 } | 1822 } |
1823 } | 1823 } |
1824 | 1824 |
1825 | 1825 |
1826 void FullCodeGenerator::VisitAssignment(Assignment* expr) { | 1826 void FullCodeGenerator::VisitAssignment(Assignment* expr) { |
1827 ASSERT(expr->target()->IsValidReferenceExpression()); | 1827 DCHECK(expr->target()->IsValidReferenceExpression()); |
1828 | 1828 |
1829 Comment cmnt(masm_, "[ Assignment"); | 1829 Comment cmnt(masm_, "[ Assignment"); |
1830 | 1830 |
1831 // Left-hand side can only be a property, a global or a (parameter or local) | 1831 // Left-hand side can only be a property, a global or a (parameter or local) |
1832 // slot. | 1832 // slot. |
1833 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; | 1833 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; |
1834 LhsKind assign_type = VARIABLE; | 1834 LhsKind assign_type = VARIABLE; |
1835 Property* property = expr->target()->AsProperty(); | 1835 Property* property = expr->target()->AsProperty(); |
1836 if (property != NULL) { | 1836 if (property != NULL) { |
1837 assign_type = (property->key()->IsPropertyName()) | 1837 assign_type = (property->key()->IsPropertyName()) |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1947 case Yield::INITIAL: { | 1947 case Yield::INITIAL: { |
1948 Label suspend, continuation, post_runtime, resume; | 1948 Label suspend, continuation, post_runtime, resume; |
1949 | 1949 |
1950 __ jmp(&suspend); | 1950 __ jmp(&suspend); |
1951 | 1951 |
1952 __ bind(&continuation); | 1952 __ bind(&continuation); |
1953 __ jmp(&resume); | 1953 __ jmp(&resume); |
1954 | 1954 |
1955 __ bind(&suspend); | 1955 __ bind(&suspend); |
1956 VisitForAccumulatorValue(expr->generator_object()); | 1956 VisitForAccumulatorValue(expr->generator_object()); |
1957 ASSERT(continuation.pos() > 0 && Smi::IsValid(continuation.pos())); | 1957 DCHECK(continuation.pos() > 0 && Smi::IsValid(continuation.pos())); |
1958 __ Move(FieldOperand(rax, JSGeneratorObject::kContinuationOffset), | 1958 __ Move(FieldOperand(rax, JSGeneratorObject::kContinuationOffset), |
1959 Smi::FromInt(continuation.pos())); | 1959 Smi::FromInt(continuation.pos())); |
1960 __ movp(FieldOperand(rax, JSGeneratorObject::kContextOffset), rsi); | 1960 __ movp(FieldOperand(rax, JSGeneratorObject::kContextOffset), rsi); |
1961 __ movp(rcx, rsi); | 1961 __ movp(rcx, rsi); |
1962 __ RecordWriteField(rax, JSGeneratorObject::kContextOffset, rcx, rdx, | 1962 __ RecordWriteField(rax, JSGeneratorObject::kContextOffset, rcx, rdx, |
1963 kDontSaveFPRegs); | 1963 kDontSaveFPRegs); |
1964 __ leap(rbx, Operand(rbp, StandardFrameConstants::kExpressionsOffset)); | 1964 __ leap(rbx, Operand(rbp, StandardFrameConstants::kExpressionsOffset)); |
1965 __ cmpp(rsp, rbx); | 1965 __ cmpp(rsp, rbx); |
1966 __ j(equal, &post_runtime); | 1966 __ j(equal, &post_runtime); |
1967 __ Push(rax); // generator object | 1967 __ Push(rax); // generator object |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2023 __ PushTryHandler(StackHandler::CATCH, expr->index()); | 2023 __ PushTryHandler(StackHandler::CATCH, expr->index()); |
2024 const int handler_size = StackHandlerConstants::kSize; | 2024 const int handler_size = StackHandlerConstants::kSize; |
2025 __ Push(rax); // result | 2025 __ Push(rax); // result |
2026 __ jmp(&l_suspend); | 2026 __ jmp(&l_suspend); |
2027 __ bind(&l_continuation); | 2027 __ bind(&l_continuation); |
2028 __ jmp(&l_resume); | 2028 __ jmp(&l_resume); |
2029 __ bind(&l_suspend); | 2029 __ bind(&l_suspend); |
2030 const int generator_object_depth = kPointerSize + handler_size; | 2030 const int generator_object_depth = kPointerSize + handler_size; |
2031 __ movp(rax, Operand(rsp, generator_object_depth)); | 2031 __ movp(rax, Operand(rsp, generator_object_depth)); |
2032 __ Push(rax); // g | 2032 __ Push(rax); // g |
2033 ASSERT(l_continuation.pos() > 0 && Smi::IsValid(l_continuation.pos())); | 2033 DCHECK(l_continuation.pos() > 0 && Smi::IsValid(l_continuation.pos())); |
2034 __ Move(FieldOperand(rax, JSGeneratorObject::kContinuationOffset), | 2034 __ Move(FieldOperand(rax, JSGeneratorObject::kContinuationOffset), |
2035 Smi::FromInt(l_continuation.pos())); | 2035 Smi::FromInt(l_continuation.pos())); |
2036 __ movp(FieldOperand(rax, JSGeneratorObject::kContextOffset), rsi); | 2036 __ movp(FieldOperand(rax, JSGeneratorObject::kContextOffset), rsi); |
2037 __ movp(rcx, rsi); | 2037 __ movp(rcx, rsi); |
2038 __ RecordWriteField(rax, JSGeneratorObject::kContextOffset, rcx, rdx, | 2038 __ RecordWriteField(rax, JSGeneratorObject::kContextOffset, rcx, rdx, |
2039 kDontSaveFPRegs); | 2039 kDontSaveFPRegs); |
2040 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); | 2040 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); |
2041 __ movp(context_register(), | 2041 __ movp(context_register(), |
2042 Operand(rbp, StandardFrameConstants::kContextOffset)); | 2042 Operand(rbp, StandardFrameConstants::kContextOffset)); |
2043 __ Pop(rax); // result | 2043 __ Pop(rax); // result |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2223 __ bind(&gc_required); | 2223 __ bind(&gc_required); |
2224 __ Push(Smi::FromInt(map->instance_size())); | 2224 __ Push(Smi::FromInt(map->instance_size())); |
2225 __ CallRuntime(Runtime::kAllocateInNewSpace, 1); | 2225 __ CallRuntime(Runtime::kAllocateInNewSpace, 1); |
2226 __ movp(context_register(), | 2226 __ movp(context_register(), |
2227 Operand(rbp, StandardFrameConstants::kContextOffset)); | 2227 Operand(rbp, StandardFrameConstants::kContextOffset)); |
2228 | 2228 |
2229 __ bind(&allocated); | 2229 __ bind(&allocated); |
2230 __ Move(rbx, map); | 2230 __ Move(rbx, map); |
2231 __ Pop(rcx); | 2231 __ Pop(rcx); |
2232 __ Move(rdx, isolate()->factory()->ToBoolean(done)); | 2232 __ Move(rdx, isolate()->factory()->ToBoolean(done)); |
2233 ASSERT_EQ(map->instance_size(), 5 * kPointerSize); | 2233 DCHECK_EQ(map->instance_size(), 5 * kPointerSize); |
2234 __ movp(FieldOperand(rax, HeapObject::kMapOffset), rbx); | 2234 __ movp(FieldOperand(rax, HeapObject::kMapOffset), rbx); |
2235 __ Move(FieldOperand(rax, JSObject::kPropertiesOffset), | 2235 __ Move(FieldOperand(rax, JSObject::kPropertiesOffset), |
2236 isolate()->factory()->empty_fixed_array()); | 2236 isolate()->factory()->empty_fixed_array()); |
2237 __ Move(FieldOperand(rax, JSObject::kElementsOffset), | 2237 __ Move(FieldOperand(rax, JSObject::kElementsOffset), |
2238 isolate()->factory()->empty_fixed_array()); | 2238 isolate()->factory()->empty_fixed_array()); |
2239 __ movp(FieldOperand(rax, JSGeneratorObject::kResultValuePropertyOffset), | 2239 __ movp(FieldOperand(rax, JSGeneratorObject::kResultValuePropertyOffset), |
2240 rcx); | 2240 rcx); |
2241 __ movp(FieldOperand(rax, JSGeneratorObject::kResultDonePropertyOffset), | 2241 __ movp(FieldOperand(rax, JSGeneratorObject::kResultDonePropertyOffset), |
2242 rdx); | 2242 rdx); |
2243 | 2243 |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2340 __ Pop(rdx); | 2340 __ Pop(rdx); |
2341 BinaryOpICStub stub(isolate(), op, mode); | 2341 BinaryOpICStub stub(isolate(), op, mode); |
2342 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. | 2342 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. |
2343 CallIC(stub.GetCode(), expr->BinaryOperationFeedbackId()); | 2343 CallIC(stub.GetCode(), expr->BinaryOperationFeedbackId()); |
2344 patch_site.EmitPatchInfo(); | 2344 patch_site.EmitPatchInfo(); |
2345 context()->Plug(rax); | 2345 context()->Plug(rax); |
2346 } | 2346 } |
2347 | 2347 |
2348 | 2348 |
2349 void FullCodeGenerator::EmitAssignment(Expression* expr) { | 2349 void FullCodeGenerator::EmitAssignment(Expression* expr) { |
2350 ASSERT(expr->IsValidReferenceExpression()); | 2350 DCHECK(expr->IsValidReferenceExpression()); |
2351 | 2351 |
2352 // Left-hand side can only be a property, a global or a (parameter or local) | 2352 // Left-hand side can only be a property, a global or a (parameter or local) |
2353 // slot. | 2353 // slot. |
2354 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; | 2354 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; |
2355 LhsKind assign_type = VARIABLE; | 2355 LhsKind assign_type = VARIABLE; |
2356 Property* prop = expr->AsProperty(); | 2356 Property* prop = expr->AsProperty(); |
2357 if (prop != NULL) { | 2357 if (prop != NULL) { |
2358 assign_type = (prop->key()->IsPropertyName()) | 2358 assign_type = (prop->key()->IsPropertyName()) |
2359 ? NAMED_PROPERTY | 2359 ? NAMED_PROPERTY |
2360 : KEYED_PROPERTY; | 2360 : KEYED_PROPERTY; |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2408 void FullCodeGenerator::EmitVariableAssignment(Variable* var, | 2408 void FullCodeGenerator::EmitVariableAssignment(Variable* var, |
2409 Token::Value op) { | 2409 Token::Value op) { |
2410 if (var->IsUnallocated()) { | 2410 if (var->IsUnallocated()) { |
2411 // Global var, const, or let. | 2411 // Global var, const, or let. |
2412 __ Move(StoreIC::NameRegister(), var->name()); | 2412 __ Move(StoreIC::NameRegister(), var->name()); |
2413 __ movp(StoreIC::ReceiverRegister(), GlobalObjectOperand()); | 2413 __ movp(StoreIC::ReceiverRegister(), GlobalObjectOperand()); |
2414 CallStoreIC(); | 2414 CallStoreIC(); |
2415 | 2415 |
2416 } else if (op == Token::INIT_CONST_LEGACY) { | 2416 } else if (op == Token::INIT_CONST_LEGACY) { |
2417 // Const initializers need a write barrier. | 2417 // Const initializers need a write barrier. |
2418 ASSERT(!var->IsParameter()); // No const parameters. | 2418 DCHECK(!var->IsParameter()); // No const parameters. |
2419 if (var->IsLookupSlot()) { | 2419 if (var->IsLookupSlot()) { |
2420 __ Push(rax); | 2420 __ Push(rax); |
2421 __ Push(rsi); | 2421 __ Push(rsi); |
2422 __ Push(var->name()); | 2422 __ Push(var->name()); |
2423 __ CallRuntime(Runtime::kInitializeLegacyConstLookupSlot, 3); | 2423 __ CallRuntime(Runtime::kInitializeLegacyConstLookupSlot, 3); |
2424 } else { | 2424 } else { |
2425 ASSERT(var->IsStackLocal() || var->IsContextSlot()); | 2425 DCHECK(var->IsStackLocal() || var->IsContextSlot()); |
2426 Label skip; | 2426 Label skip; |
2427 MemOperand location = VarOperand(var, rcx); | 2427 MemOperand location = VarOperand(var, rcx); |
2428 __ movp(rdx, location); | 2428 __ movp(rdx, location); |
2429 __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex); | 2429 __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex); |
2430 __ j(not_equal, &skip); | 2430 __ j(not_equal, &skip); |
2431 EmitStoreToStackLocalOrContextSlot(var, location); | 2431 EmitStoreToStackLocalOrContextSlot(var, location); |
2432 __ bind(&skip); | 2432 __ bind(&skip); |
2433 } | 2433 } |
2434 | 2434 |
2435 } else if (var->mode() == LET && op != Token::INIT_LET) { | 2435 } else if (var->mode() == LET && op != Token::INIT_LET) { |
2436 // Non-initializing assignment to let variable needs a write barrier. | 2436 // Non-initializing assignment to let variable needs a write barrier. |
2437 ASSERT(!var->IsLookupSlot()); | 2437 DCHECK(!var->IsLookupSlot()); |
2438 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); | 2438 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
2439 Label assign; | 2439 Label assign; |
2440 MemOperand location = VarOperand(var, rcx); | 2440 MemOperand location = VarOperand(var, rcx); |
2441 __ movp(rdx, location); | 2441 __ movp(rdx, location); |
2442 __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex); | 2442 __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex); |
2443 __ j(not_equal, &assign, Label::kNear); | 2443 __ j(not_equal, &assign, Label::kNear); |
2444 __ Push(var->name()); | 2444 __ Push(var->name()); |
2445 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 2445 __ CallRuntime(Runtime::kThrowReferenceError, 1); |
2446 __ bind(&assign); | 2446 __ bind(&assign); |
2447 EmitStoreToStackLocalOrContextSlot(var, location); | 2447 EmitStoreToStackLocalOrContextSlot(var, location); |
2448 | 2448 |
2449 } else if (!var->is_const_mode() || op == Token::INIT_CONST) { | 2449 } else if (!var->is_const_mode() || op == Token::INIT_CONST) { |
2450 if (var->IsLookupSlot()) { | 2450 if (var->IsLookupSlot()) { |
2451 // Assignment to var. | 2451 // Assignment to var. |
2452 __ Push(rax); // Value. | 2452 __ Push(rax); // Value. |
2453 __ Push(rsi); // Context. | 2453 __ Push(rsi); // Context. |
2454 __ Push(var->name()); | 2454 __ Push(var->name()); |
2455 __ Push(Smi::FromInt(strict_mode())); | 2455 __ Push(Smi::FromInt(strict_mode())); |
2456 __ CallRuntime(Runtime::kStoreLookupSlot, 4); | 2456 __ CallRuntime(Runtime::kStoreLookupSlot, 4); |
2457 } else { | 2457 } else { |
2458 // Assignment to var or initializing assignment to let/const in harmony | 2458 // Assignment to var or initializing assignment to let/const in harmony |
2459 // mode. | 2459 // mode. |
2460 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); | 2460 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
2461 MemOperand location = VarOperand(var, rcx); | 2461 MemOperand location = VarOperand(var, rcx); |
2462 if (generate_debug_code_ && op == Token::INIT_LET) { | 2462 if (generate_debug_code_ && op == Token::INIT_LET) { |
2463 // Check for an uninitialized let binding. | 2463 // Check for an uninitialized let binding. |
2464 __ movp(rdx, location); | 2464 __ movp(rdx, location); |
2465 __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex); | 2465 __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex); |
2466 __ Check(equal, kLetBindingReInitialization); | 2466 __ Check(equal, kLetBindingReInitialization); |
2467 } | 2467 } |
2468 EmitStoreToStackLocalOrContextSlot(var, location); | 2468 EmitStoreToStackLocalOrContextSlot(var, location); |
2469 } | 2469 } |
2470 } | 2470 } |
2471 // Non-initializing assignments to consts are ignored. | 2471 // Non-initializing assignments to consts are ignored. |
2472 } | 2472 } |
2473 | 2473 |
2474 | 2474 |
2475 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { | 2475 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { |
2476 // Assignment to a property, using a named store IC. | 2476 // Assignment to a property, using a named store IC. |
2477 Property* prop = expr->target()->AsProperty(); | 2477 Property* prop = expr->target()->AsProperty(); |
2478 ASSERT(prop != NULL); | 2478 DCHECK(prop != NULL); |
2479 ASSERT(prop->key()->IsLiteral()); | 2479 DCHECK(prop->key()->IsLiteral()); |
2480 | 2480 |
2481 // Record source code position before IC call. | 2481 // Record source code position before IC call. |
2482 SetSourcePosition(expr->position()); | 2482 SetSourcePosition(expr->position()); |
2483 __ Move(StoreIC::NameRegister(), prop->key()->AsLiteral()->value()); | 2483 __ Move(StoreIC::NameRegister(), prop->key()->AsLiteral()->value()); |
2484 __ Pop(StoreIC::ReceiverRegister()); | 2484 __ Pop(StoreIC::ReceiverRegister()); |
2485 CallStoreIC(expr->AssignmentFeedbackId()); | 2485 CallStoreIC(expr->AssignmentFeedbackId()); |
2486 | 2486 |
2487 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 2487 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
2488 context()->Plug(rax); | 2488 context()->Plug(rax); |
2489 } | 2489 } |
2490 | 2490 |
2491 | 2491 |
2492 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { | 2492 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { |
2493 // Assignment to a property, using a keyed store IC. | 2493 // Assignment to a property, using a keyed store IC. |
2494 | 2494 |
2495 __ Pop(KeyedStoreIC::NameRegister()); // Key. | 2495 __ Pop(KeyedStoreIC::NameRegister()); // Key. |
2496 __ Pop(KeyedStoreIC::ReceiverRegister()); | 2496 __ Pop(KeyedStoreIC::ReceiverRegister()); |
2497 ASSERT(KeyedStoreIC::ValueRegister().is(rax)); | 2497 DCHECK(KeyedStoreIC::ValueRegister().is(rax)); |
2498 // Record source code position before IC call. | 2498 // Record source code position before IC call. |
2499 SetSourcePosition(expr->position()); | 2499 SetSourcePosition(expr->position()); |
2500 Handle<Code> ic = strict_mode() == SLOPPY | 2500 Handle<Code> ic = strict_mode() == SLOPPY |
2501 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 2501 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
2502 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 2502 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
2503 CallIC(ic, expr->AssignmentFeedbackId()); | 2503 CallIC(ic, expr->AssignmentFeedbackId()); |
2504 | 2504 |
2505 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 2505 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
2506 context()->Plug(rax); | 2506 context()->Plug(rax); |
2507 } | 2507 } |
2508 | 2508 |
2509 | 2509 |
2510 void FullCodeGenerator::VisitProperty(Property* expr) { | 2510 void FullCodeGenerator::VisitProperty(Property* expr) { |
2511 Comment cmnt(masm_, "[ Property"); | 2511 Comment cmnt(masm_, "[ Property"); |
2512 Expression* key = expr->key(); | 2512 Expression* key = expr->key(); |
2513 | 2513 |
2514 if (key->IsPropertyName()) { | 2514 if (key->IsPropertyName()) { |
2515 VisitForAccumulatorValue(expr->obj()); | 2515 VisitForAccumulatorValue(expr->obj()); |
2516 ASSERT(!rax.is(LoadIC::ReceiverRegister())); | 2516 DCHECK(!rax.is(LoadIC::ReceiverRegister())); |
2517 __ movp(LoadIC::ReceiverRegister(), rax); | 2517 __ movp(LoadIC::ReceiverRegister(), rax); |
2518 EmitNamedPropertyLoad(expr); | 2518 EmitNamedPropertyLoad(expr); |
2519 PrepareForBailoutForId(expr->LoadId(), TOS_REG); | 2519 PrepareForBailoutForId(expr->LoadId(), TOS_REG); |
2520 context()->Plug(rax); | 2520 context()->Plug(rax); |
2521 } else { | 2521 } else { |
2522 VisitForStackValue(expr->obj()); | 2522 VisitForStackValue(expr->obj()); |
2523 VisitForAccumulatorValue(expr->key()); | 2523 VisitForAccumulatorValue(expr->key()); |
2524 __ Move(LoadIC::NameRegister(), rax); | 2524 __ Move(LoadIC::NameRegister(), rax); |
2525 __ Pop(LoadIC::ReceiverRegister()); | 2525 __ Pop(LoadIC::ReceiverRegister()); |
2526 EmitKeyedPropertyLoad(expr); | 2526 EmitKeyedPropertyLoad(expr); |
(...skipping 20 matching lines...) Expand all Loading... |
2547 if (call_type == CallIC::FUNCTION) { | 2547 if (call_type == CallIC::FUNCTION) { |
2548 { StackValueContext context(this); | 2548 { StackValueContext context(this); |
2549 EmitVariableLoad(callee->AsVariableProxy()); | 2549 EmitVariableLoad(callee->AsVariableProxy()); |
2550 PrepareForBailout(callee, NO_REGISTERS); | 2550 PrepareForBailout(callee, NO_REGISTERS); |
2551 } | 2551 } |
2552 // Push undefined as receiver. This is patched in the method prologue if it | 2552 // Push undefined as receiver. This is patched in the method prologue if it |
2553 // is a sloppy mode method. | 2553 // is a sloppy mode method. |
2554 __ Push(isolate()->factory()->undefined_value()); | 2554 __ Push(isolate()->factory()->undefined_value()); |
2555 } else { | 2555 } else { |
2556 // Load the function from the receiver. | 2556 // Load the function from the receiver. |
2557 ASSERT(callee->IsProperty()); | 2557 DCHECK(callee->IsProperty()); |
2558 __ movp(LoadIC::ReceiverRegister(), Operand(rsp, 0)); | 2558 __ movp(LoadIC::ReceiverRegister(), Operand(rsp, 0)); |
2559 EmitNamedPropertyLoad(callee->AsProperty()); | 2559 EmitNamedPropertyLoad(callee->AsProperty()); |
2560 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); | 2560 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); |
2561 // Push the target function under the receiver. | 2561 // Push the target function under the receiver. |
2562 __ Push(Operand(rsp, 0)); | 2562 __ Push(Operand(rsp, 0)); |
2563 __ movp(Operand(rsp, kPointerSize), rax); | 2563 __ movp(Operand(rsp, kPointerSize), rax); |
2564 } | 2564 } |
2565 | 2565 |
2566 EmitCall(expr, call_type); | 2566 EmitCall(expr, call_type); |
2567 } | 2567 } |
2568 | 2568 |
2569 | 2569 |
2570 // Common code for calls using the IC. | 2570 // Common code for calls using the IC. |
2571 void FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr, | 2571 void FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr, |
2572 Expression* key) { | 2572 Expression* key) { |
2573 // Load the key. | 2573 // Load the key. |
2574 VisitForAccumulatorValue(key); | 2574 VisitForAccumulatorValue(key); |
2575 | 2575 |
2576 Expression* callee = expr->expression(); | 2576 Expression* callee = expr->expression(); |
2577 | 2577 |
2578 // Load the function from the receiver. | 2578 // Load the function from the receiver. |
2579 ASSERT(callee->IsProperty()); | 2579 DCHECK(callee->IsProperty()); |
2580 __ movp(LoadIC::ReceiverRegister(), Operand(rsp, 0)); | 2580 __ movp(LoadIC::ReceiverRegister(), Operand(rsp, 0)); |
2581 __ Move(LoadIC::NameRegister(), rax); | 2581 __ Move(LoadIC::NameRegister(), rax); |
2582 EmitKeyedPropertyLoad(callee->AsProperty()); | 2582 EmitKeyedPropertyLoad(callee->AsProperty()); |
2583 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); | 2583 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); |
2584 | 2584 |
2585 // Push the target function under the receiver. | 2585 // Push the target function under the receiver. |
2586 __ Push(Operand(rsp, 0)); | 2586 __ Push(Operand(rsp, 0)); |
2587 __ movp(Operand(rsp, kPointerSize), rax); | 2587 __ movp(Operand(rsp, kPointerSize), rax); |
2588 | 2588 |
2589 EmitCall(expr, CallIC::METHOD); | 2589 EmitCall(expr, CallIC::METHOD); |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2730 Property* property = callee->AsProperty(); | 2730 Property* property = callee->AsProperty(); |
2731 { PreservePositionScope scope(masm()->positions_recorder()); | 2731 { PreservePositionScope scope(masm()->positions_recorder()); |
2732 VisitForStackValue(property->obj()); | 2732 VisitForStackValue(property->obj()); |
2733 } | 2733 } |
2734 if (property->key()->IsPropertyName()) { | 2734 if (property->key()->IsPropertyName()) { |
2735 EmitCallWithLoadIC(expr); | 2735 EmitCallWithLoadIC(expr); |
2736 } else { | 2736 } else { |
2737 EmitKeyedCallWithLoadIC(expr, property->key()); | 2737 EmitKeyedCallWithLoadIC(expr, property->key()); |
2738 } | 2738 } |
2739 } else { | 2739 } else { |
2740 ASSERT(call_type == Call::OTHER_CALL); | 2740 DCHECK(call_type == Call::OTHER_CALL); |
2741 // Call to an arbitrary expression not handled specially above. | 2741 // Call to an arbitrary expression not handled specially above. |
2742 { PreservePositionScope scope(masm()->positions_recorder()); | 2742 { PreservePositionScope scope(masm()->positions_recorder()); |
2743 VisitForStackValue(callee); | 2743 VisitForStackValue(callee); |
2744 } | 2744 } |
2745 __ PushRoot(Heap::kUndefinedValueRootIndex); | 2745 __ PushRoot(Heap::kUndefinedValueRootIndex); |
2746 // Emit function call. | 2746 // Emit function call. |
2747 EmitCall(expr); | 2747 EmitCall(expr); |
2748 } | 2748 } |
2749 | 2749 |
2750 #ifdef DEBUG | 2750 #ifdef DEBUG |
2751 // RecordJSReturnSite should have been called. | 2751 // RecordJSReturnSite should have been called. |
2752 ASSERT(expr->return_is_recorded_); | 2752 DCHECK(expr->return_is_recorded_); |
2753 #endif | 2753 #endif |
2754 } | 2754 } |
2755 | 2755 |
2756 | 2756 |
2757 void FullCodeGenerator::VisitCallNew(CallNew* expr) { | 2757 void FullCodeGenerator::VisitCallNew(CallNew* expr) { |
2758 Comment cmnt(masm_, "[ CallNew"); | 2758 Comment cmnt(masm_, "[ CallNew"); |
2759 // According to ECMA-262, section 11.2.2, page 44, the function | 2759 // According to ECMA-262, section 11.2.2, page 44, the function |
2760 // expression in new calls must be evaluated before the | 2760 // expression in new calls must be evaluated before the |
2761 // arguments. | 2761 // arguments. |
2762 | 2762 |
(...skipping 13 matching lines...) Expand all Loading... |
2776 // constructor invocation. | 2776 // constructor invocation. |
2777 SetSourcePosition(expr->position()); | 2777 SetSourcePosition(expr->position()); |
2778 | 2778 |
2779 // Load function and argument count into rdi and rax. | 2779 // Load function and argument count into rdi and rax. |
2780 __ Set(rax, arg_count); | 2780 __ Set(rax, arg_count); |
2781 __ movp(rdi, Operand(rsp, arg_count * kPointerSize)); | 2781 __ movp(rdi, Operand(rsp, arg_count * kPointerSize)); |
2782 | 2782 |
2783 // Record call targets in unoptimized code, but not in the snapshot. | 2783 // Record call targets in unoptimized code, but not in the snapshot. |
2784 if (FLAG_pretenuring_call_new) { | 2784 if (FLAG_pretenuring_call_new) { |
2785 EnsureSlotContainsAllocationSite(expr->AllocationSiteFeedbackSlot()); | 2785 EnsureSlotContainsAllocationSite(expr->AllocationSiteFeedbackSlot()); |
2786 ASSERT(expr->AllocationSiteFeedbackSlot() == | 2786 DCHECK(expr->AllocationSiteFeedbackSlot() == |
2787 expr->CallNewFeedbackSlot() + 1); | 2787 expr->CallNewFeedbackSlot() + 1); |
2788 } | 2788 } |
2789 | 2789 |
2790 __ Move(rbx, FeedbackVector()); | 2790 __ Move(rbx, FeedbackVector()); |
2791 __ Move(rdx, Smi::FromInt(expr->CallNewFeedbackSlot())); | 2791 __ Move(rdx, Smi::FromInt(expr->CallNewFeedbackSlot())); |
2792 | 2792 |
2793 CallConstructStub stub(isolate(), RECORD_CONSTRUCTOR_TARGET); | 2793 CallConstructStub stub(isolate(), RECORD_CONSTRUCTOR_TARGET); |
2794 __ Call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL); | 2794 __ Call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL); |
2795 PrepareForBailoutForId(expr->ReturnId(), TOS_REG); | 2795 PrepareForBailoutForId(expr->ReturnId(), TOS_REG); |
2796 context()->Plug(rax); | 2796 context()->Plug(rax); |
2797 } | 2797 } |
2798 | 2798 |
2799 | 2799 |
2800 void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) { | 2800 void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) { |
2801 ZoneList<Expression*>* args = expr->arguments(); | 2801 ZoneList<Expression*>* args = expr->arguments(); |
2802 ASSERT(args->length() == 1); | 2802 DCHECK(args->length() == 1); |
2803 | 2803 |
2804 VisitForAccumulatorValue(args->at(0)); | 2804 VisitForAccumulatorValue(args->at(0)); |
2805 | 2805 |
2806 Label materialize_true, materialize_false; | 2806 Label materialize_true, materialize_false; |
2807 Label* if_true = NULL; | 2807 Label* if_true = NULL; |
2808 Label* if_false = NULL; | 2808 Label* if_false = NULL; |
2809 Label* fall_through = NULL; | 2809 Label* fall_through = NULL; |
2810 context()->PrepareTest(&materialize_true, &materialize_false, | 2810 context()->PrepareTest(&materialize_true, &materialize_false, |
2811 &if_true, &if_false, &fall_through); | 2811 &if_true, &if_false, &fall_through); |
2812 | 2812 |
2813 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 2813 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
2814 __ JumpIfSmi(rax, if_true); | 2814 __ JumpIfSmi(rax, if_true); |
2815 __ jmp(if_false); | 2815 __ jmp(if_false); |
2816 | 2816 |
2817 context()->Plug(if_true, if_false); | 2817 context()->Plug(if_true, if_false); |
2818 } | 2818 } |
2819 | 2819 |
2820 | 2820 |
2821 void FullCodeGenerator::EmitIsNonNegativeSmi(CallRuntime* expr) { | 2821 void FullCodeGenerator::EmitIsNonNegativeSmi(CallRuntime* expr) { |
2822 ZoneList<Expression*>* args = expr->arguments(); | 2822 ZoneList<Expression*>* args = expr->arguments(); |
2823 ASSERT(args->length() == 1); | 2823 DCHECK(args->length() == 1); |
2824 | 2824 |
2825 VisitForAccumulatorValue(args->at(0)); | 2825 VisitForAccumulatorValue(args->at(0)); |
2826 | 2826 |
2827 Label materialize_true, materialize_false; | 2827 Label materialize_true, materialize_false; |
2828 Label* if_true = NULL; | 2828 Label* if_true = NULL; |
2829 Label* if_false = NULL; | 2829 Label* if_false = NULL; |
2830 Label* fall_through = NULL; | 2830 Label* fall_through = NULL; |
2831 context()->PrepareTest(&materialize_true, &materialize_false, | 2831 context()->PrepareTest(&materialize_true, &materialize_false, |
2832 &if_true, &if_false, &fall_through); | 2832 &if_true, &if_false, &fall_through); |
2833 | 2833 |
2834 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 2834 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
2835 Condition non_negative_smi = masm()->CheckNonNegativeSmi(rax); | 2835 Condition non_negative_smi = masm()->CheckNonNegativeSmi(rax); |
2836 Split(non_negative_smi, if_true, if_false, fall_through); | 2836 Split(non_negative_smi, if_true, if_false, fall_through); |
2837 | 2837 |
2838 context()->Plug(if_true, if_false); | 2838 context()->Plug(if_true, if_false); |
2839 } | 2839 } |
2840 | 2840 |
2841 | 2841 |
2842 void FullCodeGenerator::EmitIsObject(CallRuntime* expr) { | 2842 void FullCodeGenerator::EmitIsObject(CallRuntime* expr) { |
2843 ZoneList<Expression*>* args = expr->arguments(); | 2843 ZoneList<Expression*>* args = expr->arguments(); |
2844 ASSERT(args->length() == 1); | 2844 DCHECK(args->length() == 1); |
2845 | 2845 |
2846 VisitForAccumulatorValue(args->at(0)); | 2846 VisitForAccumulatorValue(args->at(0)); |
2847 | 2847 |
2848 Label materialize_true, materialize_false; | 2848 Label materialize_true, materialize_false; |
2849 Label* if_true = NULL; | 2849 Label* if_true = NULL; |
2850 Label* if_false = NULL; | 2850 Label* if_false = NULL; |
2851 Label* fall_through = NULL; | 2851 Label* fall_through = NULL; |
2852 context()->PrepareTest(&materialize_true, &materialize_false, | 2852 context()->PrepareTest(&materialize_true, &materialize_false, |
2853 &if_true, &if_false, &fall_through); | 2853 &if_true, &if_false, &fall_through); |
2854 | 2854 |
(...skipping 11 matching lines...) Expand all Loading... |
2866 __ cmpp(rbx, Immediate(LAST_NONCALLABLE_SPEC_OBJECT_TYPE)); | 2866 __ cmpp(rbx, Immediate(LAST_NONCALLABLE_SPEC_OBJECT_TYPE)); |
2867 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 2867 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
2868 Split(below_equal, if_true, if_false, fall_through); | 2868 Split(below_equal, if_true, if_false, fall_through); |
2869 | 2869 |
2870 context()->Plug(if_true, if_false); | 2870 context()->Plug(if_true, if_false); |
2871 } | 2871 } |
2872 | 2872 |
2873 | 2873 |
2874 void FullCodeGenerator::EmitIsSpecObject(CallRuntime* expr) { | 2874 void FullCodeGenerator::EmitIsSpecObject(CallRuntime* expr) { |
2875 ZoneList<Expression*>* args = expr->arguments(); | 2875 ZoneList<Expression*>* args = expr->arguments(); |
2876 ASSERT(args->length() == 1); | 2876 DCHECK(args->length() == 1); |
2877 | 2877 |
2878 VisitForAccumulatorValue(args->at(0)); | 2878 VisitForAccumulatorValue(args->at(0)); |
2879 | 2879 |
2880 Label materialize_true, materialize_false; | 2880 Label materialize_true, materialize_false; |
2881 Label* if_true = NULL; | 2881 Label* if_true = NULL; |
2882 Label* if_false = NULL; | 2882 Label* if_false = NULL; |
2883 Label* fall_through = NULL; | 2883 Label* fall_through = NULL; |
2884 context()->PrepareTest(&materialize_true, &materialize_false, | 2884 context()->PrepareTest(&materialize_true, &materialize_false, |
2885 &if_true, &if_false, &fall_through); | 2885 &if_true, &if_false, &fall_through); |
2886 | 2886 |
2887 __ JumpIfSmi(rax, if_false); | 2887 __ JumpIfSmi(rax, if_false); |
2888 __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rbx); | 2888 __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rbx); |
2889 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 2889 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
2890 Split(above_equal, if_true, if_false, fall_through); | 2890 Split(above_equal, if_true, if_false, fall_through); |
2891 | 2891 |
2892 context()->Plug(if_true, if_false); | 2892 context()->Plug(if_true, if_false); |
2893 } | 2893 } |
2894 | 2894 |
2895 | 2895 |
2896 void FullCodeGenerator::EmitIsUndetectableObject(CallRuntime* expr) { | 2896 void FullCodeGenerator::EmitIsUndetectableObject(CallRuntime* expr) { |
2897 ZoneList<Expression*>* args = expr->arguments(); | 2897 ZoneList<Expression*>* args = expr->arguments(); |
2898 ASSERT(args->length() == 1); | 2898 DCHECK(args->length() == 1); |
2899 | 2899 |
2900 VisitForAccumulatorValue(args->at(0)); | 2900 VisitForAccumulatorValue(args->at(0)); |
2901 | 2901 |
2902 Label materialize_true, materialize_false; | 2902 Label materialize_true, materialize_false; |
2903 Label* if_true = NULL; | 2903 Label* if_true = NULL; |
2904 Label* if_false = NULL; | 2904 Label* if_false = NULL; |
2905 Label* fall_through = NULL; | 2905 Label* fall_through = NULL; |
2906 context()->PrepareTest(&materialize_true, &materialize_false, | 2906 context()->PrepareTest(&materialize_true, &materialize_false, |
2907 &if_true, &if_false, &fall_through); | 2907 &if_true, &if_false, &fall_through); |
2908 | 2908 |
2909 __ JumpIfSmi(rax, if_false); | 2909 __ JumpIfSmi(rax, if_false); |
2910 __ movp(rbx, FieldOperand(rax, HeapObject::kMapOffset)); | 2910 __ movp(rbx, FieldOperand(rax, HeapObject::kMapOffset)); |
2911 __ testb(FieldOperand(rbx, Map::kBitFieldOffset), | 2911 __ testb(FieldOperand(rbx, Map::kBitFieldOffset), |
2912 Immediate(1 << Map::kIsUndetectable)); | 2912 Immediate(1 << Map::kIsUndetectable)); |
2913 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 2913 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
2914 Split(not_zero, if_true, if_false, fall_through); | 2914 Split(not_zero, if_true, if_false, fall_through); |
2915 | 2915 |
2916 context()->Plug(if_true, if_false); | 2916 context()->Plug(if_true, if_false); |
2917 } | 2917 } |
2918 | 2918 |
2919 | 2919 |
2920 void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf( | 2920 void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf( |
2921 CallRuntime* expr) { | 2921 CallRuntime* expr) { |
2922 ZoneList<Expression*>* args = expr->arguments(); | 2922 ZoneList<Expression*>* args = expr->arguments(); |
2923 ASSERT(args->length() == 1); | 2923 DCHECK(args->length() == 1); |
2924 | 2924 |
2925 VisitForAccumulatorValue(args->at(0)); | 2925 VisitForAccumulatorValue(args->at(0)); |
2926 | 2926 |
2927 Label materialize_true, materialize_false, skip_lookup; | 2927 Label materialize_true, materialize_false, skip_lookup; |
2928 Label* if_true = NULL; | 2928 Label* if_true = NULL; |
2929 Label* if_false = NULL; | 2929 Label* if_false = NULL; |
2930 Label* fall_through = NULL; | 2930 Label* fall_through = NULL; |
2931 context()->PrepareTest(&materialize_true, &materialize_false, | 2931 context()->PrepareTest(&materialize_true, &materialize_false, |
2932 &if_true, &if_false, &fall_through); | 2932 &if_true, &if_false, &fall_through); |
2933 | 2933 |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2997 ContextOperand(rdx, Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX)); | 2997 ContextOperand(rdx, Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX)); |
2998 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 2998 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
2999 Split(equal, if_true, if_false, fall_through); | 2999 Split(equal, if_true, if_false, fall_through); |
3000 | 3000 |
3001 context()->Plug(if_true, if_false); | 3001 context()->Plug(if_true, if_false); |
3002 } | 3002 } |
3003 | 3003 |
3004 | 3004 |
3005 void FullCodeGenerator::EmitIsFunction(CallRuntime* expr) { | 3005 void FullCodeGenerator::EmitIsFunction(CallRuntime* expr) { |
3006 ZoneList<Expression*>* args = expr->arguments(); | 3006 ZoneList<Expression*>* args = expr->arguments(); |
3007 ASSERT(args->length() == 1); | 3007 DCHECK(args->length() == 1); |
3008 | 3008 |
3009 VisitForAccumulatorValue(args->at(0)); | 3009 VisitForAccumulatorValue(args->at(0)); |
3010 | 3010 |
3011 Label materialize_true, materialize_false; | 3011 Label materialize_true, materialize_false; |
3012 Label* if_true = NULL; | 3012 Label* if_true = NULL; |
3013 Label* if_false = NULL; | 3013 Label* if_false = NULL; |
3014 Label* fall_through = NULL; | 3014 Label* fall_through = NULL; |
3015 context()->PrepareTest(&materialize_true, &materialize_false, | 3015 context()->PrepareTest(&materialize_true, &materialize_false, |
3016 &if_true, &if_false, &fall_through); | 3016 &if_true, &if_false, &fall_through); |
3017 | 3017 |
3018 __ JumpIfSmi(rax, if_false); | 3018 __ JumpIfSmi(rax, if_false); |
3019 __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx); | 3019 __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx); |
3020 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 3020 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
3021 Split(equal, if_true, if_false, fall_through); | 3021 Split(equal, if_true, if_false, fall_through); |
3022 | 3022 |
3023 context()->Plug(if_true, if_false); | 3023 context()->Plug(if_true, if_false); |
3024 } | 3024 } |
3025 | 3025 |
3026 | 3026 |
3027 void FullCodeGenerator::EmitIsMinusZero(CallRuntime* expr) { | 3027 void FullCodeGenerator::EmitIsMinusZero(CallRuntime* expr) { |
3028 ZoneList<Expression*>* args = expr->arguments(); | 3028 ZoneList<Expression*>* args = expr->arguments(); |
3029 ASSERT(args->length() == 1); | 3029 DCHECK(args->length() == 1); |
3030 | 3030 |
3031 VisitForAccumulatorValue(args->at(0)); | 3031 VisitForAccumulatorValue(args->at(0)); |
3032 | 3032 |
3033 Label materialize_true, materialize_false; | 3033 Label materialize_true, materialize_false; |
3034 Label* if_true = NULL; | 3034 Label* if_true = NULL; |
3035 Label* if_false = NULL; | 3035 Label* if_false = NULL; |
3036 Label* fall_through = NULL; | 3036 Label* fall_through = NULL; |
3037 context()->PrepareTest(&materialize_true, &materialize_false, | 3037 context()->PrepareTest(&materialize_true, &materialize_false, |
3038 &if_true, &if_false, &fall_through); | 3038 &if_true, &if_false, &fall_through); |
3039 | 3039 |
3040 Handle<Map> map = masm()->isolate()->factory()->heap_number_map(); | 3040 Handle<Map> map = masm()->isolate()->factory()->heap_number_map(); |
3041 __ CheckMap(rax, map, if_false, DO_SMI_CHECK); | 3041 __ CheckMap(rax, map, if_false, DO_SMI_CHECK); |
3042 __ cmpl(FieldOperand(rax, HeapNumber::kExponentOffset), | 3042 __ cmpl(FieldOperand(rax, HeapNumber::kExponentOffset), |
3043 Immediate(0x1)); | 3043 Immediate(0x1)); |
3044 __ j(no_overflow, if_false); | 3044 __ j(no_overflow, if_false); |
3045 __ cmpl(FieldOperand(rax, HeapNumber::kMantissaOffset), | 3045 __ cmpl(FieldOperand(rax, HeapNumber::kMantissaOffset), |
3046 Immediate(0x00000000)); | 3046 Immediate(0x00000000)); |
3047 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 3047 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
3048 Split(equal, if_true, if_false, fall_through); | 3048 Split(equal, if_true, if_false, fall_through); |
3049 | 3049 |
3050 context()->Plug(if_true, if_false); | 3050 context()->Plug(if_true, if_false); |
3051 } | 3051 } |
3052 | 3052 |
3053 | 3053 |
3054 void FullCodeGenerator::EmitIsArray(CallRuntime* expr) { | 3054 void FullCodeGenerator::EmitIsArray(CallRuntime* expr) { |
3055 ZoneList<Expression*>* args = expr->arguments(); | 3055 ZoneList<Expression*>* args = expr->arguments(); |
3056 ASSERT(args->length() == 1); | 3056 DCHECK(args->length() == 1); |
3057 | 3057 |
3058 VisitForAccumulatorValue(args->at(0)); | 3058 VisitForAccumulatorValue(args->at(0)); |
3059 | 3059 |
3060 Label materialize_true, materialize_false; | 3060 Label materialize_true, materialize_false; |
3061 Label* if_true = NULL; | 3061 Label* if_true = NULL; |
3062 Label* if_false = NULL; | 3062 Label* if_false = NULL; |
3063 Label* fall_through = NULL; | 3063 Label* fall_through = NULL; |
3064 context()->PrepareTest(&materialize_true, &materialize_false, | 3064 context()->PrepareTest(&materialize_true, &materialize_false, |
3065 &if_true, &if_false, &fall_through); | 3065 &if_true, &if_false, &fall_through); |
3066 | 3066 |
3067 __ JumpIfSmi(rax, if_false); | 3067 __ JumpIfSmi(rax, if_false); |
3068 __ CmpObjectType(rax, JS_ARRAY_TYPE, rbx); | 3068 __ CmpObjectType(rax, JS_ARRAY_TYPE, rbx); |
3069 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 3069 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
3070 Split(equal, if_true, if_false, fall_through); | 3070 Split(equal, if_true, if_false, fall_through); |
3071 | 3071 |
3072 context()->Plug(if_true, if_false); | 3072 context()->Plug(if_true, if_false); |
3073 } | 3073 } |
3074 | 3074 |
3075 | 3075 |
3076 void FullCodeGenerator::EmitIsRegExp(CallRuntime* expr) { | 3076 void FullCodeGenerator::EmitIsRegExp(CallRuntime* expr) { |
3077 ZoneList<Expression*>* args = expr->arguments(); | 3077 ZoneList<Expression*>* args = expr->arguments(); |
3078 ASSERT(args->length() == 1); | 3078 DCHECK(args->length() == 1); |
3079 | 3079 |
3080 VisitForAccumulatorValue(args->at(0)); | 3080 VisitForAccumulatorValue(args->at(0)); |
3081 | 3081 |
3082 Label materialize_true, materialize_false; | 3082 Label materialize_true, materialize_false; |
3083 Label* if_true = NULL; | 3083 Label* if_true = NULL; |
3084 Label* if_false = NULL; | 3084 Label* if_false = NULL; |
3085 Label* fall_through = NULL; | 3085 Label* fall_through = NULL; |
3086 context()->PrepareTest(&materialize_true, &materialize_false, | 3086 context()->PrepareTest(&materialize_true, &materialize_false, |
3087 &if_true, &if_false, &fall_through); | 3087 &if_true, &if_false, &fall_through); |
3088 | 3088 |
3089 __ JumpIfSmi(rax, if_false); | 3089 __ JumpIfSmi(rax, if_false); |
3090 __ CmpObjectType(rax, JS_REGEXP_TYPE, rbx); | 3090 __ CmpObjectType(rax, JS_REGEXP_TYPE, rbx); |
3091 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 3091 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
3092 Split(equal, if_true, if_false, fall_through); | 3092 Split(equal, if_true, if_false, fall_through); |
3093 | 3093 |
3094 context()->Plug(if_true, if_false); | 3094 context()->Plug(if_true, if_false); |
3095 } | 3095 } |
3096 | 3096 |
3097 | 3097 |
3098 | 3098 |
3099 void FullCodeGenerator::EmitIsConstructCall(CallRuntime* expr) { | 3099 void FullCodeGenerator::EmitIsConstructCall(CallRuntime* expr) { |
3100 ASSERT(expr->arguments()->length() == 0); | 3100 DCHECK(expr->arguments()->length() == 0); |
3101 | 3101 |
3102 Label materialize_true, materialize_false; | 3102 Label materialize_true, materialize_false; |
3103 Label* if_true = NULL; | 3103 Label* if_true = NULL; |
3104 Label* if_false = NULL; | 3104 Label* if_false = NULL; |
3105 Label* fall_through = NULL; | 3105 Label* fall_through = NULL; |
3106 context()->PrepareTest(&materialize_true, &materialize_false, | 3106 context()->PrepareTest(&materialize_true, &materialize_false, |
3107 &if_true, &if_false, &fall_through); | 3107 &if_true, &if_false, &fall_through); |
3108 | 3108 |
3109 // Get the frame pointer for the calling frame. | 3109 // Get the frame pointer for the calling frame. |
3110 __ movp(rax, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); | 3110 __ movp(rax, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); |
(...skipping 11 matching lines...) Expand all Loading... |
3122 Smi::FromInt(StackFrame::CONSTRUCT)); | 3122 Smi::FromInt(StackFrame::CONSTRUCT)); |
3123 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 3123 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
3124 Split(equal, if_true, if_false, fall_through); | 3124 Split(equal, if_true, if_false, fall_through); |
3125 | 3125 |
3126 context()->Plug(if_true, if_false); | 3126 context()->Plug(if_true, if_false); |
3127 } | 3127 } |
3128 | 3128 |
3129 | 3129 |
3130 void FullCodeGenerator::EmitObjectEquals(CallRuntime* expr) { | 3130 void FullCodeGenerator::EmitObjectEquals(CallRuntime* expr) { |
3131 ZoneList<Expression*>* args = expr->arguments(); | 3131 ZoneList<Expression*>* args = expr->arguments(); |
3132 ASSERT(args->length() == 2); | 3132 DCHECK(args->length() == 2); |
3133 | 3133 |
3134 // Load the two objects into registers and perform the comparison. | 3134 // Load the two objects into registers and perform the comparison. |
3135 VisitForStackValue(args->at(0)); | 3135 VisitForStackValue(args->at(0)); |
3136 VisitForAccumulatorValue(args->at(1)); | 3136 VisitForAccumulatorValue(args->at(1)); |
3137 | 3137 |
3138 Label materialize_true, materialize_false; | 3138 Label materialize_true, materialize_false; |
3139 Label* if_true = NULL; | 3139 Label* if_true = NULL; |
3140 Label* if_false = NULL; | 3140 Label* if_false = NULL; |
3141 Label* fall_through = NULL; | 3141 Label* fall_through = NULL; |
3142 context()->PrepareTest(&materialize_true, &materialize_false, | 3142 context()->PrepareTest(&materialize_true, &materialize_false, |
3143 &if_true, &if_false, &fall_through); | 3143 &if_true, &if_false, &fall_through); |
3144 | 3144 |
3145 __ Pop(rbx); | 3145 __ Pop(rbx); |
3146 __ cmpp(rax, rbx); | 3146 __ cmpp(rax, rbx); |
3147 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 3147 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
3148 Split(equal, if_true, if_false, fall_through); | 3148 Split(equal, if_true, if_false, fall_through); |
3149 | 3149 |
3150 context()->Plug(if_true, if_false); | 3150 context()->Plug(if_true, if_false); |
3151 } | 3151 } |
3152 | 3152 |
3153 | 3153 |
3154 void FullCodeGenerator::EmitArguments(CallRuntime* expr) { | 3154 void FullCodeGenerator::EmitArguments(CallRuntime* expr) { |
3155 ZoneList<Expression*>* args = expr->arguments(); | 3155 ZoneList<Expression*>* args = expr->arguments(); |
3156 ASSERT(args->length() == 1); | 3156 DCHECK(args->length() == 1); |
3157 | 3157 |
3158 // ArgumentsAccessStub expects the key in rdx and the formal | 3158 // ArgumentsAccessStub expects the key in rdx and the formal |
3159 // parameter count in rax. | 3159 // parameter count in rax. |
3160 VisitForAccumulatorValue(args->at(0)); | 3160 VisitForAccumulatorValue(args->at(0)); |
3161 __ movp(rdx, rax); | 3161 __ movp(rdx, rax); |
3162 __ Move(rax, Smi::FromInt(info_->scope()->num_parameters())); | 3162 __ Move(rax, Smi::FromInt(info_->scope()->num_parameters())); |
3163 ArgumentsAccessStub stub(isolate(), ArgumentsAccessStub::READ_ELEMENT); | 3163 ArgumentsAccessStub stub(isolate(), ArgumentsAccessStub::READ_ELEMENT); |
3164 __ CallStub(&stub); | 3164 __ CallStub(&stub); |
3165 context()->Plug(rax); | 3165 context()->Plug(rax); |
3166 } | 3166 } |
3167 | 3167 |
3168 | 3168 |
3169 void FullCodeGenerator::EmitArgumentsLength(CallRuntime* expr) { | 3169 void FullCodeGenerator::EmitArgumentsLength(CallRuntime* expr) { |
3170 ASSERT(expr->arguments()->length() == 0); | 3170 DCHECK(expr->arguments()->length() == 0); |
3171 | 3171 |
3172 Label exit; | 3172 Label exit; |
3173 // Get the number of formal parameters. | 3173 // Get the number of formal parameters. |
3174 __ Move(rax, Smi::FromInt(info_->scope()->num_parameters())); | 3174 __ Move(rax, Smi::FromInt(info_->scope()->num_parameters())); |
3175 | 3175 |
3176 // Check if the calling frame is an arguments adaptor frame. | 3176 // Check if the calling frame is an arguments adaptor frame. |
3177 __ movp(rbx, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); | 3177 __ movp(rbx, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); |
3178 __ Cmp(Operand(rbx, StandardFrameConstants::kContextOffset), | 3178 __ Cmp(Operand(rbx, StandardFrameConstants::kContextOffset), |
3179 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); | 3179 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); |
3180 __ j(not_equal, &exit, Label::kNear); | 3180 __ j(not_equal, &exit, Label::kNear); |
3181 | 3181 |
3182 // Arguments adaptor case: Read the arguments length from the | 3182 // Arguments adaptor case: Read the arguments length from the |
3183 // adaptor frame. | 3183 // adaptor frame. |
3184 __ movp(rax, Operand(rbx, ArgumentsAdaptorFrameConstants::kLengthOffset)); | 3184 __ movp(rax, Operand(rbx, ArgumentsAdaptorFrameConstants::kLengthOffset)); |
3185 | 3185 |
3186 __ bind(&exit); | 3186 __ bind(&exit); |
3187 __ AssertSmi(rax); | 3187 __ AssertSmi(rax); |
3188 context()->Plug(rax); | 3188 context()->Plug(rax); |
3189 } | 3189 } |
3190 | 3190 |
3191 | 3191 |
3192 void FullCodeGenerator::EmitClassOf(CallRuntime* expr) { | 3192 void FullCodeGenerator::EmitClassOf(CallRuntime* expr) { |
3193 ZoneList<Expression*>* args = expr->arguments(); | 3193 ZoneList<Expression*>* args = expr->arguments(); |
3194 ASSERT(args->length() == 1); | 3194 DCHECK(args->length() == 1); |
3195 Label done, null, function, non_function_constructor; | 3195 Label done, null, function, non_function_constructor; |
3196 | 3196 |
3197 VisitForAccumulatorValue(args->at(0)); | 3197 VisitForAccumulatorValue(args->at(0)); |
3198 | 3198 |
3199 // If the object is a smi, we return null. | 3199 // If the object is a smi, we return null. |
3200 __ JumpIfSmi(rax, &null); | 3200 __ JumpIfSmi(rax, &null); |
3201 | 3201 |
3202 // Check that the object is a JS object but take special care of JS | 3202 // Check that the object is a JS object but take special care of JS |
3203 // functions to make sure they have 'Function' as their class. | 3203 // functions to make sure they have 'Function' as their class. |
3204 // Assume that there are only two callable types, and one of them is at | 3204 // Assume that there are only two callable types, and one of them is at |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3247 __ bind(&done); | 3247 __ bind(&done); |
3248 | 3248 |
3249 context()->Plug(rax); | 3249 context()->Plug(rax); |
3250 } | 3250 } |
3251 | 3251 |
3252 | 3252 |
3253 void FullCodeGenerator::EmitSubString(CallRuntime* expr) { | 3253 void FullCodeGenerator::EmitSubString(CallRuntime* expr) { |
3254 // Load the arguments on the stack and call the stub. | 3254 // Load the arguments on the stack and call the stub. |
3255 SubStringStub stub(isolate()); | 3255 SubStringStub stub(isolate()); |
3256 ZoneList<Expression*>* args = expr->arguments(); | 3256 ZoneList<Expression*>* args = expr->arguments(); |
3257 ASSERT(args->length() == 3); | 3257 DCHECK(args->length() == 3); |
3258 VisitForStackValue(args->at(0)); | 3258 VisitForStackValue(args->at(0)); |
3259 VisitForStackValue(args->at(1)); | 3259 VisitForStackValue(args->at(1)); |
3260 VisitForStackValue(args->at(2)); | 3260 VisitForStackValue(args->at(2)); |
3261 __ CallStub(&stub); | 3261 __ CallStub(&stub); |
3262 context()->Plug(rax); | 3262 context()->Plug(rax); |
3263 } | 3263 } |
3264 | 3264 |
3265 | 3265 |
3266 void FullCodeGenerator::EmitRegExpExec(CallRuntime* expr) { | 3266 void FullCodeGenerator::EmitRegExpExec(CallRuntime* expr) { |
3267 // Load the arguments on the stack and call the stub. | 3267 // Load the arguments on the stack and call the stub. |
3268 RegExpExecStub stub(isolate()); | 3268 RegExpExecStub stub(isolate()); |
3269 ZoneList<Expression*>* args = expr->arguments(); | 3269 ZoneList<Expression*>* args = expr->arguments(); |
3270 ASSERT(args->length() == 4); | 3270 DCHECK(args->length() == 4); |
3271 VisitForStackValue(args->at(0)); | 3271 VisitForStackValue(args->at(0)); |
3272 VisitForStackValue(args->at(1)); | 3272 VisitForStackValue(args->at(1)); |
3273 VisitForStackValue(args->at(2)); | 3273 VisitForStackValue(args->at(2)); |
3274 VisitForStackValue(args->at(3)); | 3274 VisitForStackValue(args->at(3)); |
3275 __ CallStub(&stub); | 3275 __ CallStub(&stub); |
3276 context()->Plug(rax); | 3276 context()->Plug(rax); |
3277 } | 3277 } |
3278 | 3278 |
3279 | 3279 |
3280 void FullCodeGenerator::EmitValueOf(CallRuntime* expr) { | 3280 void FullCodeGenerator::EmitValueOf(CallRuntime* expr) { |
3281 ZoneList<Expression*>* args = expr->arguments(); | 3281 ZoneList<Expression*>* args = expr->arguments(); |
3282 ASSERT(args->length() == 1); | 3282 DCHECK(args->length() == 1); |
3283 | 3283 |
3284 VisitForAccumulatorValue(args->at(0)); // Load the object. | 3284 VisitForAccumulatorValue(args->at(0)); // Load the object. |
3285 | 3285 |
3286 Label done; | 3286 Label done; |
3287 // If the object is a smi return the object. | 3287 // If the object is a smi return the object. |
3288 __ JumpIfSmi(rax, &done); | 3288 __ JumpIfSmi(rax, &done); |
3289 // If the object is not a value type, return the object. | 3289 // If the object is not a value type, return the object. |
3290 __ CmpObjectType(rax, JS_VALUE_TYPE, rbx); | 3290 __ CmpObjectType(rax, JS_VALUE_TYPE, rbx); |
3291 __ j(not_equal, &done); | 3291 __ j(not_equal, &done); |
3292 __ movp(rax, FieldOperand(rax, JSValue::kValueOffset)); | 3292 __ movp(rax, FieldOperand(rax, JSValue::kValueOffset)); |
3293 | 3293 |
3294 __ bind(&done); | 3294 __ bind(&done); |
3295 context()->Plug(rax); | 3295 context()->Plug(rax); |
3296 } | 3296 } |
3297 | 3297 |
3298 | 3298 |
3299 void FullCodeGenerator::EmitDateField(CallRuntime* expr) { | 3299 void FullCodeGenerator::EmitDateField(CallRuntime* expr) { |
3300 ZoneList<Expression*>* args = expr->arguments(); | 3300 ZoneList<Expression*>* args = expr->arguments(); |
3301 ASSERT(args->length() == 2); | 3301 DCHECK(args->length() == 2); |
3302 ASSERT_NE(NULL, args->at(1)->AsLiteral()); | 3302 DCHECK_NE(NULL, args->at(1)->AsLiteral()); |
3303 Smi* index = Smi::cast(*(args->at(1)->AsLiteral()->value())); | 3303 Smi* index = Smi::cast(*(args->at(1)->AsLiteral()->value())); |
3304 | 3304 |
3305 VisitForAccumulatorValue(args->at(0)); // Load the object. | 3305 VisitForAccumulatorValue(args->at(0)); // Load the object. |
3306 | 3306 |
3307 Label runtime, done, not_date_object; | 3307 Label runtime, done, not_date_object; |
3308 Register object = rax; | 3308 Register object = rax; |
3309 Register result = rax; | 3309 Register result = rax; |
3310 Register scratch = rcx; | 3310 Register scratch = rcx; |
3311 | 3311 |
3312 __ JumpIfSmi(object, ¬_date_object); | 3312 __ JumpIfSmi(object, ¬_date_object); |
(...skipping 25 matching lines...) Expand all Loading... |
3338 | 3338 |
3339 __ bind(¬_date_object); | 3339 __ bind(¬_date_object); |
3340 __ CallRuntime(Runtime::kThrowNotDateError, 0); | 3340 __ CallRuntime(Runtime::kThrowNotDateError, 0); |
3341 __ bind(&done); | 3341 __ bind(&done); |
3342 context()->Plug(rax); | 3342 context()->Plug(rax); |
3343 } | 3343 } |
3344 | 3344 |
3345 | 3345 |
3346 void FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) { | 3346 void FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) { |
3347 ZoneList<Expression*>* args = expr->arguments(); | 3347 ZoneList<Expression*>* args = expr->arguments(); |
3348 ASSERT_EQ(3, args->length()); | 3348 DCHECK_EQ(3, args->length()); |
3349 | 3349 |
3350 Register string = rax; | 3350 Register string = rax; |
3351 Register index = rbx; | 3351 Register index = rbx; |
3352 Register value = rcx; | 3352 Register value = rcx; |
3353 | 3353 |
3354 VisitForStackValue(args->at(1)); // index | 3354 VisitForStackValue(args->at(1)); // index |
3355 VisitForStackValue(args->at(2)); // value | 3355 VisitForStackValue(args->at(2)); // value |
3356 VisitForAccumulatorValue(args->at(0)); // string | 3356 VisitForAccumulatorValue(args->at(0)); // string |
3357 __ Pop(value); | 3357 __ Pop(value); |
3358 __ Pop(index); | 3358 __ Pop(index); |
(...skipping 12 matching lines...) Expand all Loading... |
3371 } | 3371 } |
3372 | 3372 |
3373 __ movb(FieldOperand(string, index, times_1, SeqOneByteString::kHeaderSize), | 3373 __ movb(FieldOperand(string, index, times_1, SeqOneByteString::kHeaderSize), |
3374 value); | 3374 value); |
3375 context()->Plug(string); | 3375 context()->Plug(string); |
3376 } | 3376 } |
3377 | 3377 |
3378 | 3378 |
3379 void FullCodeGenerator::EmitTwoByteSeqStringSetChar(CallRuntime* expr) { | 3379 void FullCodeGenerator::EmitTwoByteSeqStringSetChar(CallRuntime* expr) { |
3380 ZoneList<Expression*>* args = expr->arguments(); | 3380 ZoneList<Expression*>* args = expr->arguments(); |
3381 ASSERT_EQ(3, args->length()); | 3381 DCHECK_EQ(3, args->length()); |
3382 | 3382 |
3383 Register string = rax; | 3383 Register string = rax; |
3384 Register index = rbx; | 3384 Register index = rbx; |
3385 Register value = rcx; | 3385 Register value = rcx; |
3386 | 3386 |
3387 VisitForStackValue(args->at(1)); // index | 3387 VisitForStackValue(args->at(1)); // index |
3388 VisitForStackValue(args->at(2)); // value | 3388 VisitForStackValue(args->at(2)); // value |
3389 VisitForAccumulatorValue(args->at(0)); // string | 3389 VisitForAccumulatorValue(args->at(0)); // string |
3390 __ Pop(value); | 3390 __ Pop(value); |
3391 __ Pop(index); | 3391 __ Pop(index); |
(...skipping 13 matching lines...) Expand all Loading... |
3405 | 3405 |
3406 __ movw(FieldOperand(string, index, times_2, SeqTwoByteString::kHeaderSize), | 3406 __ movw(FieldOperand(string, index, times_2, SeqTwoByteString::kHeaderSize), |
3407 value); | 3407 value); |
3408 context()->Plug(rax); | 3408 context()->Plug(rax); |
3409 } | 3409 } |
3410 | 3410 |
3411 | 3411 |
3412 void FullCodeGenerator::EmitMathPow(CallRuntime* expr) { | 3412 void FullCodeGenerator::EmitMathPow(CallRuntime* expr) { |
3413 // Load the arguments on the stack and call the runtime function. | 3413 // Load the arguments on the stack and call the runtime function. |
3414 ZoneList<Expression*>* args = expr->arguments(); | 3414 ZoneList<Expression*>* args = expr->arguments(); |
3415 ASSERT(args->length() == 2); | 3415 DCHECK(args->length() == 2); |
3416 VisitForStackValue(args->at(0)); | 3416 VisitForStackValue(args->at(0)); |
3417 VisitForStackValue(args->at(1)); | 3417 VisitForStackValue(args->at(1)); |
3418 MathPowStub stub(isolate(), MathPowStub::ON_STACK); | 3418 MathPowStub stub(isolate(), MathPowStub::ON_STACK); |
3419 __ CallStub(&stub); | 3419 __ CallStub(&stub); |
3420 context()->Plug(rax); | 3420 context()->Plug(rax); |
3421 } | 3421 } |
3422 | 3422 |
3423 | 3423 |
3424 void FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) { | 3424 void FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) { |
3425 ZoneList<Expression*>* args = expr->arguments(); | 3425 ZoneList<Expression*>* args = expr->arguments(); |
3426 ASSERT(args->length() == 2); | 3426 DCHECK(args->length() == 2); |
3427 | 3427 |
3428 VisitForStackValue(args->at(0)); // Load the object. | 3428 VisitForStackValue(args->at(0)); // Load the object. |
3429 VisitForAccumulatorValue(args->at(1)); // Load the value. | 3429 VisitForAccumulatorValue(args->at(1)); // Load the value. |
3430 __ Pop(rbx); // rax = value. rbx = object. | 3430 __ Pop(rbx); // rax = value. rbx = object. |
3431 | 3431 |
3432 Label done; | 3432 Label done; |
3433 // If the object is a smi, return the value. | 3433 // If the object is a smi, return the value. |
3434 __ JumpIfSmi(rbx, &done); | 3434 __ JumpIfSmi(rbx, &done); |
3435 | 3435 |
3436 // If the object is not a value type, return the value. | 3436 // If the object is not a value type, return the value. |
3437 __ CmpObjectType(rbx, JS_VALUE_TYPE, rcx); | 3437 __ CmpObjectType(rbx, JS_VALUE_TYPE, rcx); |
3438 __ j(not_equal, &done); | 3438 __ j(not_equal, &done); |
3439 | 3439 |
3440 // Store the value. | 3440 // Store the value. |
3441 __ movp(FieldOperand(rbx, JSValue::kValueOffset), rax); | 3441 __ movp(FieldOperand(rbx, JSValue::kValueOffset), rax); |
3442 // Update the write barrier. Save the value as it will be | 3442 // Update the write barrier. Save the value as it will be |
3443 // overwritten by the write barrier code and is needed afterward. | 3443 // overwritten by the write barrier code and is needed afterward. |
3444 __ movp(rdx, rax); | 3444 __ movp(rdx, rax); |
3445 __ RecordWriteField(rbx, JSValue::kValueOffset, rdx, rcx, kDontSaveFPRegs); | 3445 __ RecordWriteField(rbx, JSValue::kValueOffset, rdx, rcx, kDontSaveFPRegs); |
3446 | 3446 |
3447 __ bind(&done); | 3447 __ bind(&done); |
3448 context()->Plug(rax); | 3448 context()->Plug(rax); |
3449 } | 3449 } |
3450 | 3450 |
3451 | 3451 |
3452 void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) { | 3452 void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) { |
3453 ZoneList<Expression*>* args = expr->arguments(); | 3453 ZoneList<Expression*>* args = expr->arguments(); |
3454 ASSERT_EQ(args->length(), 1); | 3454 DCHECK_EQ(args->length(), 1); |
3455 | 3455 |
3456 // Load the argument into rax and call the stub. | 3456 // Load the argument into rax and call the stub. |
3457 VisitForAccumulatorValue(args->at(0)); | 3457 VisitForAccumulatorValue(args->at(0)); |
3458 | 3458 |
3459 NumberToStringStub stub(isolate()); | 3459 NumberToStringStub stub(isolate()); |
3460 __ CallStub(&stub); | 3460 __ CallStub(&stub); |
3461 context()->Plug(rax); | 3461 context()->Plug(rax); |
3462 } | 3462 } |
3463 | 3463 |
3464 | 3464 |
3465 void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) { | 3465 void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) { |
3466 ZoneList<Expression*>* args = expr->arguments(); | 3466 ZoneList<Expression*>* args = expr->arguments(); |
3467 ASSERT(args->length() == 1); | 3467 DCHECK(args->length() == 1); |
3468 | 3468 |
3469 VisitForAccumulatorValue(args->at(0)); | 3469 VisitForAccumulatorValue(args->at(0)); |
3470 | 3470 |
3471 Label done; | 3471 Label done; |
3472 StringCharFromCodeGenerator generator(rax, rbx); | 3472 StringCharFromCodeGenerator generator(rax, rbx); |
3473 generator.GenerateFast(masm_); | 3473 generator.GenerateFast(masm_); |
3474 __ jmp(&done); | 3474 __ jmp(&done); |
3475 | 3475 |
3476 NopRuntimeCallHelper call_helper; | 3476 NopRuntimeCallHelper call_helper; |
3477 generator.GenerateSlow(masm_, call_helper); | 3477 generator.GenerateSlow(masm_, call_helper); |
3478 | 3478 |
3479 __ bind(&done); | 3479 __ bind(&done); |
3480 context()->Plug(rbx); | 3480 context()->Plug(rbx); |
3481 } | 3481 } |
3482 | 3482 |
3483 | 3483 |
3484 void FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) { | 3484 void FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) { |
3485 ZoneList<Expression*>* args = expr->arguments(); | 3485 ZoneList<Expression*>* args = expr->arguments(); |
3486 ASSERT(args->length() == 2); | 3486 DCHECK(args->length() == 2); |
3487 | 3487 |
3488 VisitForStackValue(args->at(0)); | 3488 VisitForStackValue(args->at(0)); |
3489 VisitForAccumulatorValue(args->at(1)); | 3489 VisitForAccumulatorValue(args->at(1)); |
3490 | 3490 |
3491 Register object = rbx; | 3491 Register object = rbx; |
3492 Register index = rax; | 3492 Register index = rax; |
3493 Register result = rdx; | 3493 Register result = rdx; |
3494 | 3494 |
3495 __ Pop(object); | 3495 __ Pop(object); |
3496 | 3496 |
(...skipping 25 matching lines...) Expand all Loading... |
3522 NopRuntimeCallHelper call_helper; | 3522 NopRuntimeCallHelper call_helper; |
3523 generator.GenerateSlow(masm_, call_helper); | 3523 generator.GenerateSlow(masm_, call_helper); |
3524 | 3524 |
3525 __ bind(&done); | 3525 __ bind(&done); |
3526 context()->Plug(result); | 3526 context()->Plug(result); |
3527 } | 3527 } |
3528 | 3528 |
3529 | 3529 |
3530 void FullCodeGenerator::EmitStringCharAt(CallRuntime* expr) { | 3530 void FullCodeGenerator::EmitStringCharAt(CallRuntime* expr) { |
3531 ZoneList<Expression*>* args = expr->arguments(); | 3531 ZoneList<Expression*>* args = expr->arguments(); |
3532 ASSERT(args->length() == 2); | 3532 DCHECK(args->length() == 2); |
3533 | 3533 |
3534 VisitForStackValue(args->at(0)); | 3534 VisitForStackValue(args->at(0)); |
3535 VisitForAccumulatorValue(args->at(1)); | 3535 VisitForAccumulatorValue(args->at(1)); |
3536 | 3536 |
3537 Register object = rbx; | 3537 Register object = rbx; |
3538 Register index = rax; | 3538 Register index = rax; |
3539 Register scratch = rdx; | 3539 Register scratch = rdx; |
3540 Register result = rax; | 3540 Register result = rax; |
3541 | 3541 |
3542 __ Pop(object); | 3542 __ Pop(object); |
(...skipping 27 matching lines...) Expand all Loading... |
3570 NopRuntimeCallHelper call_helper; | 3570 NopRuntimeCallHelper call_helper; |
3571 generator.GenerateSlow(masm_, call_helper); | 3571 generator.GenerateSlow(masm_, call_helper); |
3572 | 3572 |
3573 __ bind(&done); | 3573 __ bind(&done); |
3574 context()->Plug(result); | 3574 context()->Plug(result); |
3575 } | 3575 } |
3576 | 3576 |
3577 | 3577 |
3578 void FullCodeGenerator::EmitStringAdd(CallRuntime* expr) { | 3578 void FullCodeGenerator::EmitStringAdd(CallRuntime* expr) { |
3579 ZoneList<Expression*>* args = expr->arguments(); | 3579 ZoneList<Expression*>* args = expr->arguments(); |
3580 ASSERT_EQ(2, args->length()); | 3580 DCHECK_EQ(2, args->length()); |
3581 VisitForStackValue(args->at(0)); | 3581 VisitForStackValue(args->at(0)); |
3582 VisitForAccumulatorValue(args->at(1)); | 3582 VisitForAccumulatorValue(args->at(1)); |
3583 | 3583 |
3584 __ Pop(rdx); | 3584 __ Pop(rdx); |
3585 StringAddStub stub(isolate(), STRING_ADD_CHECK_BOTH, NOT_TENURED); | 3585 StringAddStub stub(isolate(), STRING_ADD_CHECK_BOTH, NOT_TENURED); |
3586 __ CallStub(&stub); | 3586 __ CallStub(&stub); |
3587 context()->Plug(rax); | 3587 context()->Plug(rax); |
3588 } | 3588 } |
3589 | 3589 |
3590 | 3590 |
3591 void FullCodeGenerator::EmitStringCompare(CallRuntime* expr) { | 3591 void FullCodeGenerator::EmitStringCompare(CallRuntime* expr) { |
3592 ZoneList<Expression*>* args = expr->arguments(); | 3592 ZoneList<Expression*>* args = expr->arguments(); |
3593 ASSERT_EQ(2, args->length()); | 3593 DCHECK_EQ(2, args->length()); |
3594 | 3594 |
3595 VisitForStackValue(args->at(0)); | 3595 VisitForStackValue(args->at(0)); |
3596 VisitForStackValue(args->at(1)); | 3596 VisitForStackValue(args->at(1)); |
3597 | 3597 |
3598 StringCompareStub stub(isolate()); | 3598 StringCompareStub stub(isolate()); |
3599 __ CallStub(&stub); | 3599 __ CallStub(&stub); |
3600 context()->Plug(rax); | 3600 context()->Plug(rax); |
3601 } | 3601 } |
3602 | 3602 |
3603 | 3603 |
3604 void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) { | 3604 void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) { |
3605 ZoneList<Expression*>* args = expr->arguments(); | 3605 ZoneList<Expression*>* args = expr->arguments(); |
3606 ASSERT(args->length() >= 2); | 3606 DCHECK(args->length() >= 2); |
3607 | 3607 |
3608 int arg_count = args->length() - 2; // 2 ~ receiver and function. | 3608 int arg_count = args->length() - 2; // 2 ~ receiver and function. |
3609 for (int i = 0; i < arg_count + 1; i++) { | 3609 for (int i = 0; i < arg_count + 1; i++) { |
3610 VisitForStackValue(args->at(i)); | 3610 VisitForStackValue(args->at(i)); |
3611 } | 3611 } |
3612 VisitForAccumulatorValue(args->last()); // Function. | 3612 VisitForAccumulatorValue(args->last()); // Function. |
3613 | 3613 |
3614 Label runtime, done; | 3614 Label runtime, done; |
3615 // Check for non-function argument (including proxy). | 3615 // Check for non-function argument (including proxy). |
3616 __ JumpIfSmi(rax, &runtime); | 3616 __ JumpIfSmi(rax, &runtime); |
(...skipping 12 matching lines...) Expand all Loading... |
3629 __ CallRuntime(Runtime::kCall, args->length()); | 3629 __ CallRuntime(Runtime::kCall, args->length()); |
3630 __ bind(&done); | 3630 __ bind(&done); |
3631 | 3631 |
3632 context()->Plug(rax); | 3632 context()->Plug(rax); |
3633 } | 3633 } |
3634 | 3634 |
3635 | 3635 |
3636 void FullCodeGenerator::EmitRegExpConstructResult(CallRuntime* expr) { | 3636 void FullCodeGenerator::EmitRegExpConstructResult(CallRuntime* expr) { |
3637 RegExpConstructResultStub stub(isolate()); | 3637 RegExpConstructResultStub stub(isolate()); |
3638 ZoneList<Expression*>* args = expr->arguments(); | 3638 ZoneList<Expression*>* args = expr->arguments(); |
3639 ASSERT(args->length() == 3); | 3639 DCHECK(args->length() == 3); |
3640 VisitForStackValue(args->at(0)); | 3640 VisitForStackValue(args->at(0)); |
3641 VisitForStackValue(args->at(1)); | 3641 VisitForStackValue(args->at(1)); |
3642 VisitForAccumulatorValue(args->at(2)); | 3642 VisitForAccumulatorValue(args->at(2)); |
3643 __ Pop(rbx); | 3643 __ Pop(rbx); |
3644 __ Pop(rcx); | 3644 __ Pop(rcx); |
3645 __ CallStub(&stub); | 3645 __ CallStub(&stub); |
3646 context()->Plug(rax); | 3646 context()->Plug(rax); |
3647 } | 3647 } |
3648 | 3648 |
3649 | 3649 |
3650 void FullCodeGenerator::EmitGetFromCache(CallRuntime* expr) { | 3650 void FullCodeGenerator::EmitGetFromCache(CallRuntime* expr) { |
3651 ZoneList<Expression*>* args = expr->arguments(); | 3651 ZoneList<Expression*>* args = expr->arguments(); |
3652 ASSERT_EQ(2, args->length()); | 3652 DCHECK_EQ(2, args->length()); |
3653 | 3653 |
3654 ASSERT_NE(NULL, args->at(0)->AsLiteral()); | 3654 DCHECK_NE(NULL, args->at(0)->AsLiteral()); |
3655 int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->value()))->value(); | 3655 int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->value()))->value(); |
3656 | 3656 |
3657 Handle<FixedArray> jsfunction_result_caches( | 3657 Handle<FixedArray> jsfunction_result_caches( |
3658 isolate()->native_context()->jsfunction_result_caches()); | 3658 isolate()->native_context()->jsfunction_result_caches()); |
3659 if (jsfunction_result_caches->length() <= cache_id) { | 3659 if (jsfunction_result_caches->length() <= cache_id) { |
3660 __ Abort(kAttemptToUseUndefinedCache); | 3660 __ Abort(kAttemptToUseUndefinedCache); |
3661 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); | 3661 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); |
3662 context()->Plug(rax); | 3662 context()->Plug(rax); |
3663 return; | 3663 return; |
3664 } | 3664 } |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3699 __ Push(key); | 3699 __ Push(key); |
3700 __ CallRuntime(Runtime::kGetFromCache, 2); | 3700 __ CallRuntime(Runtime::kGetFromCache, 2); |
3701 | 3701 |
3702 __ bind(&done); | 3702 __ bind(&done); |
3703 context()->Plug(rax); | 3703 context()->Plug(rax); |
3704 } | 3704 } |
3705 | 3705 |
3706 | 3706 |
3707 void FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) { | 3707 void FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) { |
3708 ZoneList<Expression*>* args = expr->arguments(); | 3708 ZoneList<Expression*>* args = expr->arguments(); |
3709 ASSERT(args->length() == 1); | 3709 DCHECK(args->length() == 1); |
3710 | 3710 |
3711 VisitForAccumulatorValue(args->at(0)); | 3711 VisitForAccumulatorValue(args->at(0)); |
3712 | 3712 |
3713 Label materialize_true, materialize_false; | 3713 Label materialize_true, materialize_false; |
3714 Label* if_true = NULL; | 3714 Label* if_true = NULL; |
3715 Label* if_false = NULL; | 3715 Label* if_false = NULL; |
3716 Label* fall_through = NULL; | 3716 Label* fall_through = NULL; |
3717 context()->PrepareTest(&materialize_true, &materialize_false, | 3717 context()->PrepareTest(&materialize_true, &materialize_false, |
3718 &if_true, &if_false, &fall_through); | 3718 &if_true, &if_false, &fall_through); |
3719 | 3719 |
3720 __ testl(FieldOperand(rax, String::kHashFieldOffset), | 3720 __ testl(FieldOperand(rax, String::kHashFieldOffset), |
3721 Immediate(String::kContainsCachedArrayIndexMask)); | 3721 Immediate(String::kContainsCachedArrayIndexMask)); |
3722 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 3722 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
3723 __ j(zero, if_true); | 3723 __ j(zero, if_true); |
3724 __ jmp(if_false); | 3724 __ jmp(if_false); |
3725 | 3725 |
3726 context()->Plug(if_true, if_false); | 3726 context()->Plug(if_true, if_false); |
3727 } | 3727 } |
3728 | 3728 |
3729 | 3729 |
3730 void FullCodeGenerator::EmitGetCachedArrayIndex(CallRuntime* expr) { | 3730 void FullCodeGenerator::EmitGetCachedArrayIndex(CallRuntime* expr) { |
3731 ZoneList<Expression*>* args = expr->arguments(); | 3731 ZoneList<Expression*>* args = expr->arguments(); |
3732 ASSERT(args->length() == 1); | 3732 DCHECK(args->length() == 1); |
3733 VisitForAccumulatorValue(args->at(0)); | 3733 VisitForAccumulatorValue(args->at(0)); |
3734 | 3734 |
3735 __ AssertString(rax); | 3735 __ AssertString(rax); |
3736 | 3736 |
3737 __ movl(rax, FieldOperand(rax, String::kHashFieldOffset)); | 3737 __ movl(rax, FieldOperand(rax, String::kHashFieldOffset)); |
3738 ASSERT(String::kHashShift >= kSmiTagSize); | 3738 DCHECK(String::kHashShift >= kSmiTagSize); |
3739 __ IndexFromHash(rax, rax); | 3739 __ IndexFromHash(rax, rax); |
3740 | 3740 |
3741 context()->Plug(rax); | 3741 context()->Plug(rax); |
3742 } | 3742 } |
3743 | 3743 |
3744 | 3744 |
3745 void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) { | 3745 void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) { |
3746 Label bailout, return_result, done, one_char_separator, long_separator, | 3746 Label bailout, return_result, done, one_char_separator, long_separator, |
3747 non_trivial_array, not_size_one_array, loop, | 3747 non_trivial_array, not_size_one_array, loop, |
3748 loop_1, loop_1_condition, loop_2, loop_2_entry, loop_3, loop_3_entry; | 3748 loop_1, loop_1_condition, loop_2, loop_2_entry, loop_3, loop_3_entry; |
3749 ZoneList<Expression*>* args = expr->arguments(); | 3749 ZoneList<Expression*>* args = expr->arguments(); |
3750 ASSERT(args->length() == 2); | 3750 DCHECK(args->length() == 2); |
3751 // We will leave the separator on the stack until the end of the function. | 3751 // We will leave the separator on the stack until the end of the function. |
3752 VisitForStackValue(args->at(1)); | 3752 VisitForStackValue(args->at(1)); |
3753 // Load this to rax (= array) | 3753 // Load this to rax (= array) |
3754 VisitForAccumulatorValue(args->at(0)); | 3754 VisitForAccumulatorValue(args->at(0)); |
3755 // All aliases of the same register have disjoint lifetimes. | 3755 // All aliases of the same register have disjoint lifetimes. |
3756 Register array = rax; | 3756 Register array = rax; |
3757 Register elements = no_reg; // Will be rax. | 3757 Register elements = no_reg; // Will be rax. |
3758 | 3758 |
3759 Register index = rdx; | 3759 Register index = rdx; |
3760 | 3760 |
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4021 | 4021 |
4022 __ bind(&return_result); | 4022 __ bind(&return_result); |
4023 // Drop temp values from the stack, and restore context register. | 4023 // Drop temp values from the stack, and restore context register. |
4024 __ addp(rsp, Immediate(3 * kPointerSize)); | 4024 __ addp(rsp, Immediate(3 * kPointerSize)); |
4025 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 4025 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
4026 context()->Plug(rax); | 4026 context()->Plug(rax); |
4027 } | 4027 } |
4028 | 4028 |
4029 | 4029 |
4030 void FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) { | 4030 void FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) { |
4031 ASSERT(expr->arguments()->length() == 0); | 4031 DCHECK(expr->arguments()->length() == 0); |
4032 ExternalReference debug_is_active = | 4032 ExternalReference debug_is_active = |
4033 ExternalReference::debug_is_active_address(isolate()); | 4033 ExternalReference::debug_is_active_address(isolate()); |
4034 __ Move(kScratchRegister, debug_is_active); | 4034 __ Move(kScratchRegister, debug_is_active); |
4035 __ movzxbp(rax, Operand(kScratchRegister, 0)); | 4035 __ movzxbp(rax, Operand(kScratchRegister, 0)); |
4036 __ Integer32ToSmi(rax, rax); | 4036 __ Integer32ToSmi(rax, rax); |
4037 context()->Plug(rax); | 4037 context()->Plug(rax); |
4038 } | 4038 } |
4039 | 4039 |
4040 | 4040 |
4041 void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { | 4041 void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4108 if (property != NULL) { | 4108 if (property != NULL) { |
4109 VisitForStackValue(property->obj()); | 4109 VisitForStackValue(property->obj()); |
4110 VisitForStackValue(property->key()); | 4110 VisitForStackValue(property->key()); |
4111 __ Push(Smi::FromInt(strict_mode())); | 4111 __ Push(Smi::FromInt(strict_mode())); |
4112 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); | 4112 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); |
4113 context()->Plug(rax); | 4113 context()->Plug(rax); |
4114 } else if (proxy != NULL) { | 4114 } else if (proxy != NULL) { |
4115 Variable* var = proxy->var(); | 4115 Variable* var = proxy->var(); |
4116 // Delete of an unqualified identifier is disallowed in strict mode | 4116 // Delete of an unqualified identifier is disallowed in strict mode |
4117 // but "delete this" is allowed. | 4117 // but "delete this" is allowed. |
4118 ASSERT(strict_mode() == SLOPPY || var->is_this()); | 4118 DCHECK(strict_mode() == SLOPPY || var->is_this()); |
4119 if (var->IsUnallocated()) { | 4119 if (var->IsUnallocated()) { |
4120 __ Push(GlobalObjectOperand()); | 4120 __ Push(GlobalObjectOperand()); |
4121 __ Push(var->name()); | 4121 __ Push(var->name()); |
4122 __ Push(Smi::FromInt(SLOPPY)); | 4122 __ Push(Smi::FromInt(SLOPPY)); |
4123 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); | 4123 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); |
4124 context()->Plug(rax); | 4124 context()->Plug(rax); |
4125 } else if (var->IsStackAllocated() || var->IsContextSlot()) { | 4125 } else if (var->IsStackAllocated() || var->IsContextSlot()) { |
4126 // Result of deleting non-global variables is false. 'this' is | 4126 // Result of deleting non-global variables is false. 'this' is |
4127 // not really a variable, though we implement it as one. The | 4127 // not really a variable, though we implement it as one. The |
4128 // subexpression does not have side effects. | 4128 // subexpression does not have side effects. |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4163 VisitForControl(expr->expression(), | 4163 VisitForControl(expr->expression(), |
4164 test->false_label(), | 4164 test->false_label(), |
4165 test->true_label(), | 4165 test->true_label(), |
4166 test->fall_through()); | 4166 test->fall_through()); |
4167 context()->Plug(test->true_label(), test->false_label()); | 4167 context()->Plug(test->true_label(), test->false_label()); |
4168 } else { | 4168 } else { |
4169 // We handle value contexts explicitly rather than simply visiting | 4169 // We handle value contexts explicitly rather than simply visiting |
4170 // for control and plugging the control flow into the context, | 4170 // for control and plugging the control flow into the context, |
4171 // because we need to prepare a pair of extra administrative AST ids | 4171 // because we need to prepare a pair of extra administrative AST ids |
4172 // for the optimizing compiler. | 4172 // for the optimizing compiler. |
4173 ASSERT(context()->IsAccumulatorValue() || context()->IsStackValue()); | 4173 DCHECK(context()->IsAccumulatorValue() || context()->IsStackValue()); |
4174 Label materialize_true, materialize_false, done; | 4174 Label materialize_true, materialize_false, done; |
4175 VisitForControl(expr->expression(), | 4175 VisitForControl(expr->expression(), |
4176 &materialize_false, | 4176 &materialize_false, |
4177 &materialize_true, | 4177 &materialize_true, |
4178 &materialize_true); | 4178 &materialize_true); |
4179 __ bind(&materialize_true); | 4179 __ bind(&materialize_true); |
4180 PrepareForBailoutForId(expr->MaterializeTrueId(), NO_REGISTERS); | 4180 PrepareForBailoutForId(expr->MaterializeTrueId(), NO_REGISTERS); |
4181 if (context()->IsAccumulatorValue()) { | 4181 if (context()->IsAccumulatorValue()) { |
4182 __ LoadRoot(rax, Heap::kTrueValueRootIndex); | 4182 __ LoadRoot(rax, Heap::kTrueValueRootIndex); |
4183 } else { | 4183 } else { |
(...skipping 22 matching lines...) Expand all Loading... |
4206 break; | 4206 break; |
4207 } | 4207 } |
4208 | 4208 |
4209 default: | 4209 default: |
4210 UNREACHABLE(); | 4210 UNREACHABLE(); |
4211 } | 4211 } |
4212 } | 4212 } |
4213 | 4213 |
4214 | 4214 |
4215 void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { | 4215 void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { |
4216 ASSERT(expr->expression()->IsValidReferenceExpression()); | 4216 DCHECK(expr->expression()->IsValidReferenceExpression()); |
4217 | 4217 |
4218 Comment cmnt(masm_, "[ CountOperation"); | 4218 Comment cmnt(masm_, "[ CountOperation"); |
4219 SetSourcePosition(expr->position()); | 4219 SetSourcePosition(expr->position()); |
4220 | 4220 |
4221 // Expression can only be a property, a global or a (parameter or local) | 4221 // Expression can only be a property, a global or a (parameter or local) |
4222 // slot. | 4222 // slot. |
4223 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; | 4223 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; |
4224 LhsKind assign_type = VARIABLE; | 4224 LhsKind assign_type = VARIABLE; |
4225 Property* prop = expr->expression()->AsProperty(); | 4225 Property* prop = expr->expression()->AsProperty(); |
4226 // In case of a property we use the uninitialized expression context | 4226 // In case of a property we use the uninitialized expression context |
4227 // of the key to detect a named property. | 4227 // of the key to detect a named property. |
4228 if (prop != NULL) { | 4228 if (prop != NULL) { |
4229 assign_type = | 4229 assign_type = |
4230 (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY; | 4230 (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY; |
4231 } | 4231 } |
4232 | 4232 |
4233 // Evaluate expression and get value. | 4233 // Evaluate expression and get value. |
4234 if (assign_type == VARIABLE) { | 4234 if (assign_type == VARIABLE) { |
4235 ASSERT(expr->expression()->AsVariableProxy()->var() != NULL); | 4235 DCHECK(expr->expression()->AsVariableProxy()->var() != NULL); |
4236 AccumulatorValueContext context(this); | 4236 AccumulatorValueContext context(this); |
4237 EmitVariableLoad(expr->expression()->AsVariableProxy()); | 4237 EmitVariableLoad(expr->expression()->AsVariableProxy()); |
4238 } else { | 4238 } else { |
4239 // Reserve space for result of postfix operation. | 4239 // Reserve space for result of postfix operation. |
4240 if (expr->is_postfix() && !context()->IsEffect()) { | 4240 if (expr->is_postfix() && !context()->IsEffect()) { |
4241 __ Push(Smi::FromInt(0)); | 4241 __ Push(Smi::FromInt(0)); |
4242 } | 4242 } |
4243 if (assign_type == NAMED_PROPERTY) { | 4243 if (assign_type == NAMED_PROPERTY) { |
4244 VisitForStackValue(prop->obj()); | 4244 VisitForStackValue(prop->obj()); |
4245 __ movp(LoadIC::ReceiverRegister(), Operand(rsp, 0)); | 4245 __ movp(LoadIC::ReceiverRegister(), Operand(rsp, 0)); |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4391 context()->Plug(rax); | 4391 context()->Plug(rax); |
4392 } | 4392 } |
4393 break; | 4393 break; |
4394 } | 4394 } |
4395 } | 4395 } |
4396 } | 4396 } |
4397 | 4397 |
4398 | 4398 |
4399 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { | 4399 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { |
4400 VariableProxy* proxy = expr->AsVariableProxy(); | 4400 VariableProxy* proxy = expr->AsVariableProxy(); |
4401 ASSERT(!context()->IsEffect()); | 4401 DCHECK(!context()->IsEffect()); |
4402 ASSERT(!context()->IsTest()); | 4402 DCHECK(!context()->IsTest()); |
4403 | 4403 |
4404 if (proxy != NULL && proxy->var()->IsUnallocated()) { | 4404 if (proxy != NULL && proxy->var()->IsUnallocated()) { |
4405 Comment cmnt(masm_, "[ Global variable"); | 4405 Comment cmnt(masm_, "[ Global variable"); |
4406 __ Move(LoadIC::NameRegister(), proxy->name()); | 4406 __ Move(LoadIC::NameRegister(), proxy->name()); |
4407 __ movp(LoadIC::ReceiverRegister(), GlobalObjectOperand()); | 4407 __ movp(LoadIC::ReceiverRegister(), GlobalObjectOperand()); |
4408 if (FLAG_vector_ics) { | 4408 if (FLAG_vector_ics) { |
4409 __ Move(LoadIC::SlotRegister(), | 4409 __ Move(LoadIC::SlotRegister(), |
4410 Smi::FromInt(proxy->VariableFeedbackSlot())); | 4410 Smi::FromInt(proxy->VariableFeedbackSlot())); |
4411 } | 4411 } |
4412 // Use a regular load, not a contextual load, to avoid a reference | 4412 // Use a regular load, not a contextual load, to avoid a reference |
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4622 return rax; | 4622 return rax; |
4623 } | 4623 } |
4624 | 4624 |
4625 | 4625 |
4626 Register FullCodeGenerator::context_register() { | 4626 Register FullCodeGenerator::context_register() { |
4627 return rsi; | 4627 return rsi; |
4628 } | 4628 } |
4629 | 4629 |
4630 | 4630 |
4631 void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { | 4631 void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { |
4632 ASSERT(IsAligned(frame_offset, kPointerSize)); | 4632 DCHECK(IsAligned(frame_offset, kPointerSize)); |
4633 __ movp(Operand(rbp, frame_offset), value); | 4633 __ movp(Operand(rbp, frame_offset), value); |
4634 } | 4634 } |
4635 | 4635 |
4636 | 4636 |
4637 void FullCodeGenerator::LoadContextField(Register dst, int context_index) { | 4637 void FullCodeGenerator::LoadContextField(Register dst, int context_index) { |
4638 __ movp(dst, ContextOperand(rsi, context_index)); | 4638 __ movp(dst, ContextOperand(rsi, context_index)); |
4639 } | 4639 } |
4640 | 4640 |
4641 | 4641 |
4642 void FullCodeGenerator::PushFunctionArgumentForContextAllocation() { | 4642 void FullCodeGenerator::PushFunctionArgumentForContextAllocation() { |
4643 Scope* declaration_scope = scope()->DeclarationScope(); | 4643 Scope* declaration_scope = scope()->DeclarationScope(); |
4644 if (declaration_scope->is_global_scope() || | 4644 if (declaration_scope->is_global_scope() || |
4645 declaration_scope->is_module_scope()) { | 4645 declaration_scope->is_module_scope()) { |
4646 // Contexts nested in the native context have a canonical empty function | 4646 // Contexts nested in the native context have a canonical empty function |
4647 // as their closure, not the anonymous closure containing the global | 4647 // as their closure, not the anonymous closure containing the global |
4648 // code. Pass a smi sentinel and let the runtime look up the empty | 4648 // code. Pass a smi sentinel and let the runtime look up the empty |
4649 // function. | 4649 // function. |
4650 __ Push(Smi::FromInt(0)); | 4650 __ Push(Smi::FromInt(0)); |
4651 } else if (declaration_scope->is_eval_scope()) { | 4651 } else if (declaration_scope->is_eval_scope()) { |
4652 // Contexts created by a call to eval have the same closure as the | 4652 // Contexts created by a call to eval have the same closure as the |
4653 // context calling eval, not the anonymous closure containing the eval | 4653 // context calling eval, not the anonymous closure containing the eval |
4654 // code. Fetch it from the context. | 4654 // code. Fetch it from the context. |
4655 __ Push(ContextOperand(rsi, Context::CLOSURE_INDEX)); | 4655 __ Push(ContextOperand(rsi, Context::CLOSURE_INDEX)); |
4656 } else { | 4656 } else { |
4657 ASSERT(declaration_scope->is_function_scope()); | 4657 DCHECK(declaration_scope->is_function_scope()); |
4658 __ Push(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); | 4658 __ Push(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); |
4659 } | 4659 } |
4660 } | 4660 } |
4661 | 4661 |
4662 | 4662 |
4663 // ---------------------------------------------------------------------------- | 4663 // ---------------------------------------------------------------------------- |
4664 // Non-local control flow support. | 4664 // Non-local control flow support. |
4665 | 4665 |
4666 | 4666 |
4667 void FullCodeGenerator::EnterFinallyBlock() { | 4667 void FullCodeGenerator::EnterFinallyBlock() { |
4668 ASSERT(!result_register().is(rdx)); | 4668 DCHECK(!result_register().is(rdx)); |
4669 ASSERT(!result_register().is(rcx)); | 4669 DCHECK(!result_register().is(rcx)); |
4670 // Cook return address on top of stack (smi encoded Code* delta) | 4670 // Cook return address on top of stack (smi encoded Code* delta) |
4671 __ PopReturnAddressTo(rdx); | 4671 __ PopReturnAddressTo(rdx); |
4672 __ Move(rcx, masm_->CodeObject()); | 4672 __ Move(rcx, masm_->CodeObject()); |
4673 __ subp(rdx, rcx); | 4673 __ subp(rdx, rcx); |
4674 __ Integer32ToSmi(rdx, rdx); | 4674 __ Integer32ToSmi(rdx, rdx); |
4675 __ Push(rdx); | 4675 __ Push(rdx); |
4676 | 4676 |
4677 // Store result register while executing finally block. | 4677 // Store result register while executing finally block. |
4678 __ Push(result_register()); | 4678 __ Push(result_register()); |
4679 | 4679 |
(...skipping 10 matching lines...) Expand all Loading... |
4690 __ Push(rdx); | 4690 __ Push(rdx); |
4691 | 4691 |
4692 ExternalReference pending_message_script = | 4692 ExternalReference pending_message_script = |
4693 ExternalReference::address_of_pending_message_script(isolate()); | 4693 ExternalReference::address_of_pending_message_script(isolate()); |
4694 __ Load(rdx, pending_message_script); | 4694 __ Load(rdx, pending_message_script); |
4695 __ Push(rdx); | 4695 __ Push(rdx); |
4696 } | 4696 } |
4697 | 4697 |
4698 | 4698 |
4699 void FullCodeGenerator::ExitFinallyBlock() { | 4699 void FullCodeGenerator::ExitFinallyBlock() { |
4700 ASSERT(!result_register().is(rdx)); | 4700 DCHECK(!result_register().is(rdx)); |
4701 ASSERT(!result_register().is(rcx)); | 4701 DCHECK(!result_register().is(rcx)); |
4702 // Restore pending message from stack. | 4702 // Restore pending message from stack. |
4703 __ Pop(rdx); | 4703 __ Pop(rdx); |
4704 ExternalReference pending_message_script = | 4704 ExternalReference pending_message_script = |
4705 ExternalReference::address_of_pending_message_script(isolate()); | 4705 ExternalReference::address_of_pending_message_script(isolate()); |
4706 __ Store(pending_message_script, rdx); | 4706 __ Store(pending_message_script, rdx); |
4707 | 4707 |
4708 __ Pop(rdx); | 4708 __ Pop(rdx); |
4709 __ SmiToInteger32(rdx, rdx); | 4709 __ SmiToInteger32(rdx, rdx); |
4710 ExternalReference has_pending_message = | 4710 ExternalReference has_pending_message = |
4711 ExternalReference::address_of_has_pending_message(isolate()); | 4711 ExternalReference::address_of_has_pending_message(isolate()); |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4803 unoptimized_code, call_target_address, replacement_code); | 4803 unoptimized_code, call_target_address, replacement_code); |
4804 } | 4804 } |
4805 | 4805 |
4806 | 4806 |
4807 BackEdgeTable::BackEdgeState BackEdgeTable::GetBackEdgeState( | 4807 BackEdgeTable::BackEdgeState BackEdgeTable::GetBackEdgeState( |
4808 Isolate* isolate, | 4808 Isolate* isolate, |
4809 Code* unoptimized_code, | 4809 Code* unoptimized_code, |
4810 Address pc) { | 4810 Address pc) { |
4811 Address call_target_address = pc - kIntSize; | 4811 Address call_target_address = pc - kIntSize; |
4812 Address jns_instr_address = call_target_address - 3; | 4812 Address jns_instr_address = call_target_address - 3; |
4813 ASSERT_EQ(kCallInstruction, *(call_target_address - 1)); | 4813 DCHECK_EQ(kCallInstruction, *(call_target_address - 1)); |
4814 | 4814 |
4815 if (*jns_instr_address == kJnsInstruction) { | 4815 if (*jns_instr_address == kJnsInstruction) { |
4816 ASSERT_EQ(kJnsOffset, *(call_target_address - 2)); | 4816 DCHECK_EQ(kJnsOffset, *(call_target_address - 2)); |
4817 ASSERT_EQ(isolate->builtins()->InterruptCheck()->entry(), | 4817 DCHECK_EQ(isolate->builtins()->InterruptCheck()->entry(), |
4818 Assembler::target_address_at(call_target_address, | 4818 Assembler::target_address_at(call_target_address, |
4819 unoptimized_code)); | 4819 unoptimized_code)); |
4820 return INTERRUPT; | 4820 return INTERRUPT; |
4821 } | 4821 } |
4822 | 4822 |
4823 ASSERT_EQ(kNopByteOne, *jns_instr_address); | 4823 DCHECK_EQ(kNopByteOne, *jns_instr_address); |
4824 ASSERT_EQ(kNopByteTwo, *(call_target_address - 2)); | 4824 DCHECK_EQ(kNopByteTwo, *(call_target_address - 2)); |
4825 | 4825 |
4826 if (Assembler::target_address_at(call_target_address, | 4826 if (Assembler::target_address_at(call_target_address, |
4827 unoptimized_code) == | 4827 unoptimized_code) == |
4828 isolate->builtins()->OnStackReplacement()->entry()) { | 4828 isolate->builtins()->OnStackReplacement()->entry()) { |
4829 return ON_STACK_REPLACEMENT; | 4829 return ON_STACK_REPLACEMENT; |
4830 } | 4830 } |
4831 | 4831 |
4832 ASSERT_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(), | 4832 DCHECK_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(), |
4833 Assembler::target_address_at(call_target_address, | 4833 Assembler::target_address_at(call_target_address, |
4834 unoptimized_code)); | 4834 unoptimized_code)); |
4835 return OSR_AFTER_STACK_CHECK; | 4835 return OSR_AFTER_STACK_CHECK; |
4836 } | 4836 } |
4837 | 4837 |
4838 | 4838 |
4839 } } // namespace v8::internal | 4839 } } // namespace v8::internal |
4840 | 4840 |
4841 #endif // V8_TARGET_ARCH_X64 | 4841 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |