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

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

Issue 430503007: Rename ASSERT* to DCHECK*. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: REBASE and fixes Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/x64/disasm-x64.cc ('k') | src/x64/ic-x64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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, &not_date_object); 3312 __ JumpIfSmi(object, &not_date_object);
(...skipping 25 matching lines...) Expand all
3338 3338
3339 __ bind(&not_date_object); 3339 __ bind(&not_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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/x64/disasm-x64.cc ('k') | src/x64/ic-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698