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