| 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_X87 | 7 #if V8_TARGET_ARCH_X87 |
| 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 distance = Label::kFar) { | 39 Label::Distance distance = Label::kFar) { |
| 40 __ test(reg, Immediate(kSmiTagMask)); | 40 __ test(reg, Immediate(kSmiTagMask)); |
| 41 EmitJump(not_carry, target, distance); // Always taken before patched. | 41 EmitJump(not_carry, target, distance); // 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 distance = Label::kFar) { | 46 Label::Distance distance = Label::kFar) { |
| 47 __ test(reg, Immediate(kSmiTagMask)); | 47 __ test(reg, Immediate(kSmiTagMask)); |
| 48 EmitJump(carry, target, distance); // Never taken before patched. | 48 EmitJump(carry, target, distance); // 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 __ test(eax, Immediate(delta_to_patch_site)); | 55 __ test(eax, 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 distance) { | 66 void EmitJump(Condition cc, Label* target, Label::Distance distance) { |
| 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, distance); | 70 __ j(cc, target, distance); |
| 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 __ push(Immediate(isolate()->factory()->undefined_value())); | 147 __ push(Immediate(isolate()->factory()->undefined_value())); |
| 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 __ mov(ecx, esp); | 151 __ mov(ecx, esp); |
| 152 __ sub(ecx, Immediate(locals_count * kPointerSize)); | 152 __ sub(ecx, Immediate(locals_count * kPointerSize)); |
| 153 ExternalReference stack_limit = | 153 ExternalReference stack_limit = |
| 154 ExternalReference::address_of_real_stack_limit(isolate()); | 154 ExternalReference::address_of_real_stack_limit(isolate()); |
| 155 __ cmp(ecx, Operand::StaticVariable(stack_limit)); | 155 __ cmp(ecx, Operand::StaticVariable(stack_limit)); |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 278 Comment cmnt(masm_, "[ Declarations"); | 278 Comment cmnt(masm_, "[ Declarations"); |
| 279 scope()->VisitIllegalRedeclaration(this); | 279 scope()->VisitIllegalRedeclaration(this); |
| 280 | 280 |
| 281 } else { | 281 } else { |
| 282 PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS); | 282 PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS); |
| 283 { Comment cmnt(masm_, "[ Declarations"); | 283 { Comment cmnt(masm_, "[ Declarations"); |
| 284 // For named function expressions, declare the function name as a | 284 // For named function expressions, declare the function name as a |
| 285 // constant. | 285 // constant. |
| 286 if (scope()->is_function_scope() && scope()->function() != NULL) { | 286 if (scope()->is_function_scope() && scope()->function() != NULL) { |
| 287 VariableDeclaration* function = scope()->function(); | 287 VariableDeclaration* function = scope()->function(); |
| 288 ASSERT(function->proxy()->var()->mode() == CONST || | 288 DCHECK(function->proxy()->var()->mode() == CONST || |
| 289 function->proxy()->var()->mode() == CONST_LEGACY); | 289 function->proxy()->var()->mode() == CONST_LEGACY); |
| 290 ASSERT(function->proxy()->var()->location() != Variable::UNALLOCATED); | 290 DCHECK(function->proxy()->var()->location() != Variable::UNALLOCATED); |
| 291 VisitVariableDeclaration(function); | 291 VisitVariableDeclaration(function); |
| 292 } | 292 } |
| 293 VisitDeclarations(scope()->declarations()); | 293 VisitDeclarations(scope()->declarations()); |
| 294 } | 294 } |
| 295 | 295 |
| 296 { Comment cmnt(masm_, "[ Stack check"); | 296 { Comment cmnt(masm_, "[ Stack check"); |
| 297 PrepareForBailoutForId(BailoutId::Declarations(), NO_REGISTERS); | 297 PrepareForBailoutForId(BailoutId::Declarations(), NO_REGISTERS); |
| 298 Label ok; | 298 Label ok; |
| 299 ExternalReference stack_limit | 299 ExternalReference stack_limit |
| 300 = ExternalReference::address_of_stack_limit(isolate()); | 300 = ExternalReference::address_of_stack_limit(isolate()); |
| 301 __ cmp(esp, Operand::StaticVariable(stack_limit)); | 301 __ cmp(esp, Operand::StaticVariable(stack_limit)); |
| 302 __ j(above_equal, &ok, Label::kNear); | 302 __ j(above_equal, &ok, Label::kNear); |
| 303 __ call(isolate()->builtins()->StackCheck(), RelocInfo::CODE_TARGET); | 303 __ call(isolate()->builtins()->StackCheck(), RelocInfo::CODE_TARGET); |
| 304 __ bind(&ok); | 304 __ bind(&ok); |
| 305 } | 305 } |
| 306 | 306 |
| 307 { Comment cmnt(masm_, "[ Body"); | 307 { Comment cmnt(masm_, "[ Body"); |
| 308 ASSERT(loop_depth() == 0); | 308 DCHECK(loop_depth() == 0); |
| 309 VisitStatements(function()->body()); | 309 VisitStatements(function()->body()); |
| 310 ASSERT(loop_depth() == 0); | 310 DCHECK(loop_depth() == 0); |
| 311 } | 311 } |
| 312 } | 312 } |
| 313 | 313 |
| 314 // Always emit a 'return undefined' in case control fell off the end of | 314 // Always emit a 'return undefined' in case control fell off the end of |
| 315 // the body. | 315 // the body. |
| 316 { Comment cmnt(masm_, "[ return <undefined>;"); | 316 { Comment cmnt(masm_, "[ return <undefined>;"); |
| 317 __ mov(eax, isolate()->factory()->undefined_value()); | 317 __ mov(eax, isolate()->factory()->undefined_value()); |
| 318 EmitReturnSequence(); | 318 EmitReturnSequence(); |
| 319 } | 319 } |
| 320 } | 320 } |
| (...skipping 17 matching lines...) Expand all Loading... |
| 338 __ mov(FieldOperand(ebx, Cell::kValueOffset), | 338 __ mov(FieldOperand(ebx, Cell::kValueOffset), |
| 339 Immediate(Smi::FromInt(reset_value))); | 339 Immediate(Smi::FromInt(reset_value))); |
| 340 } | 340 } |
| 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 __ j(positive, &ok, Label::kNear); | 353 __ j(positive, &ok, Label::kNear); |
| 354 __ call(isolate()->builtins()->InterruptCheck(), RelocInfo::CODE_TARGET); | 354 __ call(isolate()->builtins()->InterruptCheck(), RelocInfo::CODE_TARGET); |
| 355 | 355 |
| 356 // Record a mapping of this PC offset to the OSR id. This is used to find | 356 // Record a mapping of this PC offset to the OSR id. This is used to find |
| 357 // the AST id from the unoptimized code in order to use it as a key into | 357 // the AST id from the unoptimized code in order to use it as a key into |
| 358 // the deoptimization input data found in the optimized code. | 358 // the deoptimization input data found in the optimized code. |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 408 // Do not use the leave instruction here because it is too short to | 408 // Do not use the leave instruction here because it is too short to |
| 409 // patch with the code required by the debugger. | 409 // patch with the code required by the debugger. |
| 410 __ mov(esp, ebp); | 410 __ mov(esp, ebp); |
| 411 int no_frame_start = masm_->pc_offset(); | 411 int no_frame_start = masm_->pc_offset(); |
| 412 __ pop(ebp); | 412 __ pop(ebp); |
| 413 | 413 |
| 414 int arguments_bytes = (info_->scope()->num_parameters() + 1) * kPointerSize; | 414 int arguments_bytes = (info_->scope()->num_parameters() + 1) * kPointerSize; |
| 415 __ Ret(arguments_bytes, ecx); | 415 __ Ret(arguments_bytes, ecx); |
| 416 // Check that the size of the code used for returning is large enough | 416 // Check that the size of the code used for returning is large enough |
| 417 // for the debugger's requirements. | 417 // for the debugger's requirements. |
| 418 ASSERT(Assembler::kJSReturnSequenceLength <= | 418 DCHECK(Assembler::kJSReturnSequenceLength <= |
| 419 masm_->SizeOfCodeGeneratedSince(&check_exit_codesize)); | 419 masm_->SizeOfCodeGeneratedSince(&check_exit_codesize)); |
| 420 info_->AddNoFrameRange(no_frame_start, masm_->pc_offset()); | 420 info_->AddNoFrameRange(no_frame_start, masm_->pc_offset()); |
| 421 } | 421 } |
| 422 } | 422 } |
| 423 | 423 |
| 424 | 424 |
| 425 void FullCodeGenerator::EffectContext::Plug(Variable* var) const { | 425 void FullCodeGenerator::EffectContext::Plug(Variable* var) const { |
| 426 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); | 426 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
| 427 } | 427 } |
| 428 | 428 |
| 429 | 429 |
| 430 void FullCodeGenerator::AccumulatorValueContext::Plug(Variable* var) const { | 430 void FullCodeGenerator::AccumulatorValueContext::Plug(Variable* var) const { |
| 431 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); | 431 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
| 432 codegen()->GetVar(result_register(), var); | 432 codegen()->GetVar(result_register(), var); |
| 433 } | 433 } |
| 434 | 434 |
| 435 | 435 |
| 436 void FullCodeGenerator::StackValueContext::Plug(Variable* var) const { | 436 void FullCodeGenerator::StackValueContext::Plug(Variable* var) const { |
| 437 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); | 437 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
| 438 MemOperand operand = codegen()->VarOperand(var, result_register()); | 438 MemOperand operand = codegen()->VarOperand(var, result_register()); |
| 439 // Memory operands can be pushed directly. | 439 // Memory operands can be pushed directly. |
| 440 __ push(operand); | 440 __ push(operand); |
| 441 } | 441 } |
| 442 | 442 |
| 443 | 443 |
| 444 void FullCodeGenerator::TestContext::Plug(Variable* var) const { | 444 void FullCodeGenerator::TestContext::Plug(Variable* var) const { |
| 445 // For simplicity we always test the accumulator register. | 445 // For simplicity we always test the accumulator register. |
| 446 codegen()->GetVar(result_register(), var); | 446 codegen()->GetVar(result_register(), var); |
| 447 codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL); | 447 codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 492 __ push(Immediate(lit)); | 492 __ push(Immediate(lit)); |
| 493 } | 493 } |
| 494 } | 494 } |
| 495 | 495 |
| 496 | 496 |
| 497 void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const { | 497 void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const { |
| 498 codegen()->PrepareForBailoutBeforeSplit(condition(), | 498 codegen()->PrepareForBailoutBeforeSplit(condition(), |
| 499 true, | 499 true, |
| 500 true_label_, | 500 true_label_, |
| 501 false_label_); | 501 false_label_); |
| 502 ASSERT(!lit->IsUndetectableObject()); // There are no undetectable literals. | 502 DCHECK(!lit->IsUndetectableObject()); // There are no undetectable literals. |
| 503 if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) { | 503 if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) { |
| 504 if (false_label_ != fall_through_) __ jmp(false_label_); | 504 if (false_label_ != fall_through_) __ jmp(false_label_); |
| 505 } else if (lit->IsTrue() || lit->IsJSObject()) { | 505 } else if (lit->IsTrue() || lit->IsJSObject()) { |
| 506 if (true_label_ != fall_through_) __ jmp(true_label_); | 506 if (true_label_ != fall_through_) __ jmp(true_label_); |
| 507 } else if (lit->IsString()) { | 507 } else if (lit->IsString()) { |
| 508 if (String::cast(*lit)->length() == 0) { | 508 if (String::cast(*lit)->length() == 0) { |
| 509 if (false_label_ != fall_through_) __ jmp(false_label_); | 509 if (false_label_ != fall_through_) __ jmp(false_label_); |
| 510 } else { | 510 } else { |
| 511 if (true_label_ != fall_through_) __ jmp(true_label_); | 511 if (true_label_ != fall_through_) __ jmp(true_label_); |
| 512 } | 512 } |
| 513 } else if (lit->IsSmi()) { | 513 } else if (lit->IsSmi()) { |
| 514 if (Smi::cast(*lit)->value() == 0) { | 514 if (Smi::cast(*lit)->value() == 0) { |
| 515 if (false_label_ != fall_through_) __ jmp(false_label_); | 515 if (false_label_ != fall_through_) __ jmp(false_label_); |
| 516 } else { | 516 } else { |
| 517 if (true_label_ != fall_through_) __ jmp(true_label_); | 517 if (true_label_ != fall_through_) __ jmp(true_label_); |
| 518 } | 518 } |
| 519 } else { | 519 } else { |
| 520 // For simplicity we always test the accumulator register. | 520 // For simplicity we always test the accumulator register. |
| 521 __ mov(result_register(), lit); | 521 __ mov(result_register(), lit); |
| 522 codegen()->DoTest(this); | 522 codegen()->DoTest(this); |
| 523 } | 523 } |
| 524 } | 524 } |
| 525 | 525 |
| 526 | 526 |
| 527 void FullCodeGenerator::EffectContext::DropAndPlug(int count, | 527 void FullCodeGenerator::EffectContext::DropAndPlug(int count, |
| 528 Register reg) const { | 528 Register reg) const { |
| 529 ASSERT(count > 0); | 529 DCHECK(count > 0); |
| 530 __ Drop(count); | 530 __ Drop(count); |
| 531 } | 531 } |
| 532 | 532 |
| 533 | 533 |
| 534 void FullCodeGenerator::AccumulatorValueContext::DropAndPlug( | 534 void FullCodeGenerator::AccumulatorValueContext::DropAndPlug( |
| 535 int count, | 535 int count, |
| 536 Register reg) const { | 536 Register reg) const { |
| 537 ASSERT(count > 0); | 537 DCHECK(count > 0); |
| 538 __ Drop(count); | 538 __ Drop(count); |
| 539 __ Move(result_register(), reg); | 539 __ Move(result_register(), reg); |
| 540 } | 540 } |
| 541 | 541 |
| 542 | 542 |
| 543 void FullCodeGenerator::StackValueContext::DropAndPlug(int count, | 543 void FullCodeGenerator::StackValueContext::DropAndPlug(int count, |
| 544 Register reg) const { | 544 Register reg) const { |
| 545 ASSERT(count > 0); | 545 DCHECK(count > 0); |
| 546 if (count > 1) __ Drop(count - 1); | 546 if (count > 1) __ Drop(count - 1); |
| 547 __ mov(Operand(esp, 0), reg); | 547 __ mov(Operand(esp, 0), reg); |
| 548 } | 548 } |
| 549 | 549 |
| 550 | 550 |
| 551 void FullCodeGenerator::TestContext::DropAndPlug(int count, | 551 void FullCodeGenerator::TestContext::DropAndPlug(int count, |
| 552 Register reg) const { | 552 Register reg) const { |
| 553 ASSERT(count > 0); | 553 DCHECK(count > 0); |
| 554 // For simplicity we always test the accumulator register. | 554 // For simplicity we always test the accumulator register. |
| 555 __ Drop(count); | 555 __ Drop(count); |
| 556 __ Move(result_register(), reg); | 556 __ Move(result_register(), reg); |
| 557 codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL); | 557 codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL); |
| 558 codegen()->DoTest(this); | 558 codegen()->DoTest(this); |
| 559 } | 559 } |
| 560 | 560 |
| 561 | 561 |
| 562 void FullCodeGenerator::EffectContext::Plug(Label* materialize_true, | 562 void FullCodeGenerator::EffectContext::Plug(Label* materialize_true, |
| 563 Label* materialize_false) const { | 563 Label* materialize_false) const { |
| 564 ASSERT(materialize_true == materialize_false); | 564 DCHECK(materialize_true == materialize_false); |
| 565 __ bind(materialize_true); | 565 __ bind(materialize_true); |
| 566 } | 566 } |
| 567 | 567 |
| 568 | 568 |
| 569 void FullCodeGenerator::AccumulatorValueContext::Plug( | 569 void FullCodeGenerator::AccumulatorValueContext::Plug( |
| 570 Label* materialize_true, | 570 Label* materialize_true, |
| 571 Label* materialize_false) const { | 571 Label* materialize_false) const { |
| 572 Label done; | 572 Label done; |
| 573 __ bind(materialize_true); | 573 __ bind(materialize_true); |
| 574 __ mov(result_register(), isolate()->factory()->true_value()); | 574 __ mov(result_register(), isolate()->factory()->true_value()); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 587 __ push(Immediate(isolate()->factory()->true_value())); | 587 __ push(Immediate(isolate()->factory()->true_value())); |
| 588 __ jmp(&done, Label::kNear); | 588 __ jmp(&done, Label::kNear); |
| 589 __ bind(materialize_false); | 589 __ bind(materialize_false); |
| 590 __ push(Immediate(isolate()->factory()->false_value())); | 590 __ push(Immediate(isolate()->factory()->false_value())); |
| 591 __ bind(&done); | 591 __ bind(&done); |
| 592 } | 592 } |
| 593 | 593 |
| 594 | 594 |
| 595 void FullCodeGenerator::TestContext::Plug(Label* materialize_true, | 595 void FullCodeGenerator::TestContext::Plug(Label* materialize_true, |
| 596 Label* materialize_false) const { | 596 Label* materialize_false) const { |
| 597 ASSERT(materialize_true == true_label_); | 597 DCHECK(materialize_true == true_label_); |
| 598 ASSERT(materialize_false == false_label_); | 598 DCHECK(materialize_false == false_label_); |
| 599 } | 599 } |
| 600 | 600 |
| 601 | 601 |
| 602 void FullCodeGenerator::EffectContext::Plug(bool flag) const { | 602 void FullCodeGenerator::EffectContext::Plug(bool flag) const { |
| 603 } | 603 } |
| 604 | 604 |
| 605 | 605 |
| 606 void FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const { | 606 void FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const { |
| 607 Handle<Object> value = flag | 607 Handle<Object> value = flag |
| 608 ? isolate()->factory()->true_value() | 608 ? isolate()->factory()->true_value() |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 653 } else if (if_true == fall_through) { | 653 } else if (if_true == fall_through) { |
| 654 __ j(NegateCondition(cc), if_false); | 654 __ j(NegateCondition(cc), if_false); |
| 655 } else { | 655 } else { |
| 656 __ j(cc, if_true); | 656 __ j(cc, if_true); |
| 657 __ jmp(if_false); | 657 __ jmp(if_false); |
| 658 } | 658 } |
| 659 } | 659 } |
| 660 | 660 |
| 661 | 661 |
| 662 MemOperand FullCodeGenerator::StackOperand(Variable* var) { | 662 MemOperand FullCodeGenerator::StackOperand(Variable* var) { |
| 663 ASSERT(var->IsStackAllocated()); | 663 DCHECK(var->IsStackAllocated()); |
| 664 // Offset is negative because higher indexes are at lower addresses. | 664 // Offset is negative because higher indexes are at lower addresses. |
| 665 int offset = -var->index() * kPointerSize; | 665 int offset = -var->index() * kPointerSize; |
| 666 // Adjust by a (parameter or local) base offset. | 666 // Adjust by a (parameter or local) base offset. |
| 667 if (var->IsParameter()) { | 667 if (var->IsParameter()) { |
| 668 offset += (info_->scope()->num_parameters() + 1) * kPointerSize; | 668 offset += (info_->scope()->num_parameters() + 1) * kPointerSize; |
| 669 } else { | 669 } else { |
| 670 offset += JavaScriptFrameConstants::kLocal0Offset; | 670 offset += JavaScriptFrameConstants::kLocal0Offset; |
| 671 } | 671 } |
| 672 return Operand(ebp, offset); | 672 return Operand(ebp, offset); |
| 673 } | 673 } |
| 674 | 674 |
| 675 | 675 |
| 676 MemOperand FullCodeGenerator::VarOperand(Variable* var, Register scratch) { | 676 MemOperand FullCodeGenerator::VarOperand(Variable* var, Register scratch) { |
| 677 ASSERT(var->IsContextSlot() || var->IsStackAllocated()); | 677 DCHECK(var->IsContextSlot() || var->IsStackAllocated()); |
| 678 if (var->IsContextSlot()) { | 678 if (var->IsContextSlot()) { |
| 679 int context_chain_length = scope()->ContextChainLength(var->scope()); | 679 int context_chain_length = scope()->ContextChainLength(var->scope()); |
| 680 __ LoadContext(scratch, context_chain_length); | 680 __ LoadContext(scratch, context_chain_length); |
| 681 return ContextOperand(scratch, var->index()); | 681 return ContextOperand(scratch, var->index()); |
| 682 } else { | 682 } else { |
| 683 return StackOperand(var); | 683 return StackOperand(var); |
| 684 } | 684 } |
| 685 } | 685 } |
| 686 | 686 |
| 687 | 687 |
| 688 void FullCodeGenerator::GetVar(Register dest, Variable* var) { | 688 void FullCodeGenerator::GetVar(Register dest, Variable* var) { |
| 689 ASSERT(var->IsContextSlot() || var->IsStackAllocated()); | 689 DCHECK(var->IsContextSlot() || var->IsStackAllocated()); |
| 690 MemOperand location = VarOperand(var, dest); | 690 MemOperand location = VarOperand(var, dest); |
| 691 __ mov(dest, location); | 691 __ mov(dest, location); |
| 692 } | 692 } |
| 693 | 693 |
| 694 | 694 |
| 695 void FullCodeGenerator::SetVar(Variable* var, | 695 void FullCodeGenerator::SetVar(Variable* var, |
| 696 Register src, | 696 Register src, |
| 697 Register scratch0, | 697 Register scratch0, |
| 698 Register scratch1) { | 698 Register scratch1) { |
| 699 ASSERT(var->IsContextSlot() || var->IsStackAllocated()); | 699 DCHECK(var->IsContextSlot() || var->IsStackAllocated()); |
| 700 ASSERT(!scratch0.is(src)); | 700 DCHECK(!scratch0.is(src)); |
| 701 ASSERT(!scratch0.is(scratch1)); | 701 DCHECK(!scratch0.is(scratch1)); |
| 702 ASSERT(!scratch1.is(src)); | 702 DCHECK(!scratch1.is(src)); |
| 703 MemOperand location = VarOperand(var, scratch0); | 703 MemOperand location = VarOperand(var, scratch0); |
| 704 __ mov(location, src); | 704 __ mov(location, src); |
| 705 | 705 |
| 706 // Emit the write barrier code if the location is in the heap. | 706 // Emit the write barrier code if the location is in the heap. |
| 707 if (var->IsContextSlot()) { | 707 if (var->IsContextSlot()) { |
| 708 int offset = Context::SlotOffset(var->index()); | 708 int offset = Context::SlotOffset(var->index()); |
| 709 ASSERT(!scratch0.is(esi) && !src.is(esi) && !scratch1.is(esi)); | 709 DCHECK(!scratch0.is(esi) && !src.is(esi) && !scratch1.is(esi)); |
| 710 __ RecordWriteContextSlot(scratch0, offset, src, scratch1); | 710 __ RecordWriteContextSlot(scratch0, offset, src, scratch1); |
| 711 } | 711 } |
| 712 } | 712 } |
| 713 | 713 |
| 714 | 714 |
| 715 void FullCodeGenerator::PrepareForBailoutBeforeSplit(Expression* expr, | 715 void FullCodeGenerator::PrepareForBailoutBeforeSplit(Expression* expr, |
| 716 bool should_normalize, | 716 bool should_normalize, |
| 717 Label* if_true, | 717 Label* if_true, |
| 718 Label* if_false) { | 718 Label* if_false) { |
| 719 // Only prepare for bailouts before splits if we're in a test | 719 // Only prepare for bailouts before splits if we're in a test |
| 720 // context. Otherwise, we let the Visit function deal with the | 720 // context. Otherwise, we let the Visit function deal with the |
| 721 // preparation to avoid preparing with the same AST id twice. | 721 // preparation to avoid preparing with the same AST id twice. |
| 722 if (!context()->IsTest() || !info_->IsOptimizable()) return; | 722 if (!context()->IsTest() || !info_->IsOptimizable()) return; |
| 723 | 723 |
| 724 Label skip; | 724 Label skip; |
| 725 if (should_normalize) __ jmp(&skip, Label::kNear); | 725 if (should_normalize) __ jmp(&skip, Label::kNear); |
| 726 PrepareForBailout(expr, TOS_REG); | 726 PrepareForBailout(expr, TOS_REG); |
| 727 if (should_normalize) { | 727 if (should_normalize) { |
| 728 __ cmp(eax, isolate()->factory()->true_value()); | 728 __ cmp(eax, isolate()->factory()->true_value()); |
| 729 Split(equal, if_true, if_false, NULL); | 729 Split(equal, if_true, if_false, NULL); |
| 730 __ bind(&skip); | 730 __ bind(&skip); |
| 731 } | 731 } |
| 732 } | 732 } |
| 733 | 733 |
| 734 | 734 |
| 735 void FullCodeGenerator::EmitDebugCheckDeclarationContext(Variable* variable) { | 735 void FullCodeGenerator::EmitDebugCheckDeclarationContext(Variable* variable) { |
| 736 // The variable in the declaration always resides in the current context. | 736 // The variable in the declaration always resides in the current context. |
| 737 ASSERT_EQ(0, scope()->ContextChainLength(variable->scope())); | 737 DCHECK_EQ(0, scope()->ContextChainLength(variable->scope())); |
| 738 if (generate_debug_code_) { | 738 if (generate_debug_code_) { |
| 739 // Check that we're not inside a with or catch context. | 739 // Check that we're not inside a with or catch context. |
| 740 __ mov(ebx, FieldOperand(esi, HeapObject::kMapOffset)); | 740 __ mov(ebx, FieldOperand(esi, HeapObject::kMapOffset)); |
| 741 __ cmp(ebx, isolate()->factory()->with_context_map()); | 741 __ cmp(ebx, isolate()->factory()->with_context_map()); |
| 742 __ Check(not_equal, kDeclarationInWithContext); | 742 __ Check(not_equal, kDeclarationInWithContext); |
| 743 __ cmp(ebx, isolate()->factory()->catch_context_map()); | 743 __ cmp(ebx, isolate()->factory()->catch_context_map()); |
| 744 __ Check(not_equal, kDeclarationInCatchContext); | 744 __ Check(not_equal, kDeclarationInCatchContext); |
| 745 } | 745 } |
| 746 } | 746 } |
| 747 | 747 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 781 // No write barrier since the hole value is in old space. | 781 // No write barrier since the hole value is in old space. |
| 782 PrepareForBailoutForId(proxy->id(), NO_REGISTERS); | 782 PrepareForBailoutForId(proxy->id(), NO_REGISTERS); |
| 783 } | 783 } |
| 784 break; | 784 break; |
| 785 | 785 |
| 786 case Variable::LOOKUP: { | 786 case Variable::LOOKUP: { |
| 787 Comment cmnt(masm_, "[ VariableDeclaration"); | 787 Comment cmnt(masm_, "[ VariableDeclaration"); |
| 788 __ push(esi); | 788 __ push(esi); |
| 789 __ push(Immediate(variable->name())); | 789 __ push(Immediate(variable->name())); |
| 790 // VariableDeclaration nodes are always introduced in one of four modes. | 790 // VariableDeclaration nodes are always introduced in one of four modes. |
| 791 ASSERT(IsDeclaredVariableMode(mode)); | 791 DCHECK(IsDeclaredVariableMode(mode)); |
| 792 PropertyAttributes attr = | 792 PropertyAttributes attr = |
| 793 IsImmutableVariableMode(mode) ? READ_ONLY : NONE; | 793 IsImmutableVariableMode(mode) ? READ_ONLY : NONE; |
| 794 __ push(Immediate(Smi::FromInt(attr))); | 794 __ push(Immediate(Smi::FromInt(attr))); |
| 795 // Push initial value, if any. | 795 // Push initial value, if any. |
| 796 // Note: For variables we must not push an initial value (such as | 796 // Note: For variables we must not push an initial value (such as |
| 797 // 'undefined') because we may have a (legal) redeclaration and we | 797 // 'undefined') because we may have a (legal) redeclaration and we |
| 798 // must not destroy the current value. | 798 // must not destroy the current value. |
| 799 if (hole_init) { | 799 if (hole_init) { |
| 800 __ push(Immediate(isolate()->factory()->the_hole_value())); | 800 __ push(Immediate(isolate()->factory()->the_hole_value())); |
| 801 } else { | 801 } else { |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 855 VisitForStackValue(declaration->fun()); | 855 VisitForStackValue(declaration->fun()); |
| 856 __ CallRuntime(Runtime::kDeclareLookupSlot, 4); | 856 __ CallRuntime(Runtime::kDeclareLookupSlot, 4); |
| 857 break; | 857 break; |
| 858 } | 858 } |
| 859 } | 859 } |
| 860 } | 860 } |
| 861 | 861 |
| 862 | 862 |
| 863 void FullCodeGenerator::VisitModuleDeclaration(ModuleDeclaration* declaration) { | 863 void FullCodeGenerator::VisitModuleDeclaration(ModuleDeclaration* declaration) { |
| 864 Variable* variable = declaration->proxy()->var(); | 864 Variable* variable = declaration->proxy()->var(); |
| 865 ASSERT(variable->location() == Variable::CONTEXT); | 865 DCHECK(variable->location() == Variable::CONTEXT); |
| 866 ASSERT(variable->interface()->IsFrozen()); | 866 DCHECK(variable->interface()->IsFrozen()); |
| 867 | 867 |
| 868 Comment cmnt(masm_, "[ ModuleDeclaration"); | 868 Comment cmnt(masm_, "[ ModuleDeclaration"); |
| 869 EmitDebugCheckDeclarationContext(variable); | 869 EmitDebugCheckDeclarationContext(variable); |
| 870 | 870 |
| 871 // Load instance object. | 871 // Load instance object. |
| 872 __ LoadContext(eax, scope_->ContextChainLength(scope_->GlobalScope())); | 872 __ LoadContext(eax, scope_->ContextChainLength(scope_->GlobalScope())); |
| 873 __ mov(eax, ContextOperand(eax, variable->interface()->Index())); | 873 __ mov(eax, ContextOperand(eax, variable->interface()->Index())); |
| 874 __ mov(eax, ContextOperand(eax, Context::EXTENSION_INDEX)); | 874 __ mov(eax, ContextOperand(eax, Context::EXTENSION_INDEX)); |
| 875 | 875 |
| 876 // Assign it. | 876 // Assign it. |
| (...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1145 | 1145 |
| 1146 // Check if the expected map still matches that of the enumerable. | 1146 // Check if the expected map still matches that of the enumerable. |
| 1147 // If not, we may have to filter the key. | 1147 // If not, we may have to filter the key. |
| 1148 Label update_each; | 1148 Label update_each; |
| 1149 __ mov(ecx, Operand(esp, 4 * kPointerSize)); | 1149 __ mov(ecx, Operand(esp, 4 * kPointerSize)); |
| 1150 __ cmp(edx, FieldOperand(ecx, HeapObject::kMapOffset)); | 1150 __ cmp(edx, FieldOperand(ecx, HeapObject::kMapOffset)); |
| 1151 __ j(equal, &update_each, Label::kNear); | 1151 __ j(equal, &update_each, Label::kNear); |
| 1152 | 1152 |
| 1153 // For proxies, no filtering is done. | 1153 // For proxies, no filtering is done. |
| 1154 // TODO(rossberg): What if only a prototype is a proxy? Not specified yet. | 1154 // TODO(rossberg): What if only a prototype is a proxy? Not specified yet. |
| 1155 ASSERT(Smi::FromInt(0) == 0); | 1155 DCHECK(Smi::FromInt(0) == 0); |
| 1156 __ test(edx, edx); | 1156 __ test(edx, edx); |
| 1157 __ j(zero, &update_each); | 1157 __ j(zero, &update_each); |
| 1158 | 1158 |
| 1159 // Convert the entry to a string or null if it isn't a property | 1159 // Convert the entry to a string or null if it isn't a property |
| 1160 // anymore. If the property has been removed while iterating, we | 1160 // anymore. If the property has been removed while iterating, we |
| 1161 // just skip it. | 1161 // just skip it. |
| 1162 __ push(ecx); // Enumerable. | 1162 __ push(ecx); // Enumerable. |
| 1163 __ push(ebx); // Current entry. | 1163 __ push(ebx); // Current entry. |
| 1164 __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION); | 1164 __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION); |
| 1165 __ test(eax, eax); | 1165 __ test(eax, eax); |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1335 ContextualMode mode = (typeof_state == INSIDE_TYPEOF) | 1335 ContextualMode mode = (typeof_state == INSIDE_TYPEOF) |
| 1336 ? NOT_CONTEXTUAL | 1336 ? NOT_CONTEXTUAL |
| 1337 : CONTEXTUAL; | 1337 : CONTEXTUAL; |
| 1338 | 1338 |
| 1339 CallLoadIC(mode); | 1339 CallLoadIC(mode); |
| 1340 } | 1340 } |
| 1341 | 1341 |
| 1342 | 1342 |
| 1343 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, | 1343 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, |
| 1344 Label* slow) { | 1344 Label* slow) { |
| 1345 ASSERT(var->IsContextSlot()); | 1345 DCHECK(var->IsContextSlot()); |
| 1346 Register context = esi; | 1346 Register context = esi; |
| 1347 Register temp = ebx; | 1347 Register temp = ebx; |
| 1348 | 1348 |
| 1349 for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) { | 1349 for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) { |
| 1350 if (s->num_heap_slots() > 0) { | 1350 if (s->num_heap_slots() > 0) { |
| 1351 if (s->calls_sloppy_eval()) { | 1351 if (s->calls_sloppy_eval()) { |
| 1352 // Check that extension is NULL. | 1352 // Check that extension is NULL. |
| 1353 __ cmp(ContextOperand(context, Context::EXTENSION_INDEX), | 1353 __ cmp(ContextOperand(context, Context::EXTENSION_INDEX), |
| 1354 Immediate(0)); | 1354 Immediate(0)); |
| 1355 __ j(not_equal, slow); | 1355 __ j(not_equal, slow); |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1427 case Variable::LOCAL: | 1427 case Variable::LOCAL: |
| 1428 case Variable::CONTEXT: { | 1428 case Variable::CONTEXT: { |
| 1429 Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable" | 1429 Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable" |
| 1430 : "[ Stack variable"); | 1430 : "[ Stack variable"); |
| 1431 if (var->binding_needs_init()) { | 1431 if (var->binding_needs_init()) { |
| 1432 // var->scope() may be NULL when the proxy is located in eval code and | 1432 // var->scope() may be NULL when the proxy is located in eval code and |
| 1433 // refers to a potential outside binding. Currently those bindings are | 1433 // refers to a potential outside binding. Currently those bindings are |
| 1434 // always looked up dynamically, i.e. in that case | 1434 // always looked up dynamically, i.e. in that case |
| 1435 // var->location() == LOOKUP. | 1435 // var->location() == LOOKUP. |
| 1436 // always holds. | 1436 // always holds. |
| 1437 ASSERT(var->scope() != NULL); | 1437 DCHECK(var->scope() != NULL); |
| 1438 | 1438 |
| 1439 // Check if the binding really needs an initialization check. The check | 1439 // Check if the binding really needs an initialization check. The check |
| 1440 // can be skipped in the following situation: we have a LET or CONST | 1440 // can be skipped in the following situation: we have a LET or CONST |
| 1441 // binding in harmony mode, both the Variable and the VariableProxy have | 1441 // binding in harmony mode, both the Variable and the VariableProxy have |
| 1442 // the same declaration scope (i.e. they are both in global code, in the | 1442 // the same declaration scope (i.e. they are both in global code, in the |
| 1443 // same function or in the same eval code) and the VariableProxy is in | 1443 // same function or in the same eval code) and the VariableProxy is in |
| 1444 // the source physically located after the initializer of the variable. | 1444 // the source physically located after the initializer of the variable. |
| 1445 // | 1445 // |
| 1446 // We cannot skip any initialization checks for CONST in non-harmony | 1446 // We cannot skip any initialization checks for CONST in non-harmony |
| 1447 // mode because const variables may be declared but never initialized: | 1447 // mode because const variables may be declared but never initialized: |
| 1448 // if (false) { const x; }; var y = x; | 1448 // if (false) { const x; }; var y = x; |
| 1449 // | 1449 // |
| 1450 // The condition on the declaration scopes is a conservative check for | 1450 // The condition on the declaration scopes is a conservative check for |
| 1451 // nested functions that access a binding and are called before the | 1451 // nested functions that access a binding and are called before the |
| 1452 // binding is initialized: | 1452 // binding is initialized: |
| 1453 // function() { f(); let x = 1; function f() { x = 2; } } | 1453 // function() { f(); let x = 1; function f() { x = 2; } } |
| 1454 // | 1454 // |
| 1455 bool skip_init_check; | 1455 bool skip_init_check; |
| 1456 if (var->scope()->DeclarationScope() != scope()->DeclarationScope()) { | 1456 if (var->scope()->DeclarationScope() != scope()->DeclarationScope()) { |
| 1457 skip_init_check = false; | 1457 skip_init_check = false; |
| 1458 } else { | 1458 } else { |
| 1459 // Check that we always have valid source position. | 1459 // Check that we always have valid source position. |
| 1460 ASSERT(var->initializer_position() != RelocInfo::kNoPosition); | 1460 DCHECK(var->initializer_position() != RelocInfo::kNoPosition); |
| 1461 ASSERT(proxy->position() != RelocInfo::kNoPosition); | 1461 DCHECK(proxy->position() != RelocInfo::kNoPosition); |
| 1462 skip_init_check = var->mode() != CONST_LEGACY && | 1462 skip_init_check = var->mode() != CONST_LEGACY && |
| 1463 var->initializer_position() < proxy->position(); | 1463 var->initializer_position() < proxy->position(); |
| 1464 } | 1464 } |
| 1465 | 1465 |
| 1466 if (!skip_init_check) { | 1466 if (!skip_init_check) { |
| 1467 // Let and const need a read barrier. | 1467 // Let and const need a read barrier. |
| 1468 Label done; | 1468 Label done; |
| 1469 GetVar(eax, var); | 1469 GetVar(eax, var); |
| 1470 __ cmp(eax, isolate()->factory()->the_hole_value()); | 1470 __ cmp(eax, isolate()->factory()->the_hole_value()); |
| 1471 __ j(not_equal, &done, Label::kNear); | 1471 __ j(not_equal, &done, Label::kNear); |
| 1472 if (var->mode() == LET || var->mode() == CONST) { | 1472 if (var->mode() == LET || var->mode() == CONST) { |
| 1473 // Throw a reference error when using an uninitialized let/const | 1473 // Throw a reference error when using an uninitialized let/const |
| 1474 // binding in harmony mode. | 1474 // binding in harmony mode. |
| 1475 __ push(Immediate(var->name())); | 1475 __ push(Immediate(var->name())); |
| 1476 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 1476 __ CallRuntime(Runtime::kThrowReferenceError, 1); |
| 1477 } else { | 1477 } else { |
| 1478 // Uninitalized const bindings outside of harmony mode are unholed. | 1478 // Uninitalized const bindings outside of harmony mode are unholed. |
| 1479 ASSERT(var->mode() == CONST_LEGACY); | 1479 DCHECK(var->mode() == CONST_LEGACY); |
| 1480 __ mov(eax, isolate()->factory()->undefined_value()); | 1480 __ mov(eax, isolate()->factory()->undefined_value()); |
| 1481 } | 1481 } |
| 1482 __ bind(&done); | 1482 __ bind(&done); |
| 1483 context()->Plug(eax); | 1483 context()->Plug(eax); |
| 1484 break; | 1484 break; |
| 1485 } | 1485 } |
| 1486 } | 1486 } |
| 1487 context()->Plug(var); | 1487 context()->Plug(var); |
| 1488 break; | 1488 break; |
| 1489 } | 1489 } |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1618 Literal* key = property->key(); | 1618 Literal* key = property->key(); |
| 1619 Expression* value = property->value(); | 1619 Expression* value = property->value(); |
| 1620 if (!result_saved) { | 1620 if (!result_saved) { |
| 1621 __ push(eax); // Save result on the stack | 1621 __ push(eax); // Save result on the stack |
| 1622 result_saved = true; | 1622 result_saved = true; |
| 1623 } | 1623 } |
| 1624 switch (property->kind()) { | 1624 switch (property->kind()) { |
| 1625 case ObjectLiteral::Property::CONSTANT: | 1625 case ObjectLiteral::Property::CONSTANT: |
| 1626 UNREACHABLE(); | 1626 UNREACHABLE(); |
| 1627 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | 1627 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
| 1628 ASSERT(!CompileTimeValue::IsCompileTimeValue(value)); | 1628 DCHECK(!CompileTimeValue::IsCompileTimeValue(value)); |
| 1629 // Fall through. | 1629 // Fall through. |
| 1630 case ObjectLiteral::Property::COMPUTED: | 1630 case ObjectLiteral::Property::COMPUTED: |
| 1631 if (key->value()->IsInternalizedString()) { | 1631 if (key->value()->IsInternalizedString()) { |
| 1632 if (property->emit_store()) { | 1632 if (property->emit_store()) { |
| 1633 VisitForAccumulatorValue(value); | 1633 VisitForAccumulatorValue(value); |
| 1634 ASSERT(StoreIC::ValueRegister().is(eax)); | 1634 DCHECK(StoreIC::ValueRegister().is(eax)); |
| 1635 __ mov(StoreIC::NameRegister(), Immediate(key->value())); | 1635 __ mov(StoreIC::NameRegister(), Immediate(key->value())); |
| 1636 __ mov(StoreIC::ReceiverRegister(), Operand(esp, 0)); | 1636 __ mov(StoreIC::ReceiverRegister(), Operand(esp, 0)); |
| 1637 CallStoreIC(key->LiteralFeedbackId()); | 1637 CallStoreIC(key->LiteralFeedbackId()); |
| 1638 PrepareForBailoutForId(key->id(), NO_REGISTERS); | 1638 PrepareForBailoutForId(key->id(), NO_REGISTERS); |
| 1639 } else { | 1639 } else { |
| 1640 VisitForEffect(value); | 1640 VisitForEffect(value); |
| 1641 } | 1641 } |
| 1642 break; | 1642 break; |
| 1643 } | 1643 } |
| 1644 __ push(Operand(esp, 0)); // Duplicate receiver. | 1644 __ push(Operand(esp, 0)); // Duplicate receiver. |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1676 ++it) { | 1676 ++it) { |
| 1677 __ push(Operand(esp, 0)); // Duplicate receiver. | 1677 __ push(Operand(esp, 0)); // Duplicate receiver. |
| 1678 VisitForStackValue(it->first); | 1678 VisitForStackValue(it->first); |
| 1679 EmitAccessor(it->second->getter); | 1679 EmitAccessor(it->second->getter); |
| 1680 EmitAccessor(it->second->setter); | 1680 EmitAccessor(it->second->setter); |
| 1681 __ push(Immediate(Smi::FromInt(NONE))); | 1681 __ push(Immediate(Smi::FromInt(NONE))); |
| 1682 __ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5); | 1682 __ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5); |
| 1683 } | 1683 } |
| 1684 | 1684 |
| 1685 if (expr->has_function()) { | 1685 if (expr->has_function()) { |
| 1686 ASSERT(result_saved); | 1686 DCHECK(result_saved); |
| 1687 __ push(Operand(esp, 0)); | 1687 __ push(Operand(esp, 0)); |
| 1688 __ CallRuntime(Runtime::kToFastProperties, 1); | 1688 __ CallRuntime(Runtime::kToFastProperties, 1); |
| 1689 } | 1689 } |
| 1690 | 1690 |
| 1691 if (result_saved) { | 1691 if (result_saved) { |
| 1692 context()->PlugTOS(); | 1692 context()->PlugTOS(); |
| 1693 } else { | 1693 } else { |
| 1694 context()->Plug(eax); | 1694 context()->Plug(eax); |
| 1695 } | 1695 } |
| 1696 } | 1696 } |
| 1697 | 1697 |
| 1698 | 1698 |
| 1699 void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { | 1699 void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { |
| 1700 Comment cmnt(masm_, "[ ArrayLiteral"); | 1700 Comment cmnt(masm_, "[ ArrayLiteral"); |
| 1701 | 1701 |
| 1702 expr->BuildConstantElements(isolate()); | 1702 expr->BuildConstantElements(isolate()); |
| 1703 int flags = expr->depth() == 1 | 1703 int flags = expr->depth() == 1 |
| 1704 ? ArrayLiteral::kShallowElements | 1704 ? ArrayLiteral::kShallowElements |
| 1705 : ArrayLiteral::kNoFlags; | 1705 : ArrayLiteral::kNoFlags; |
| 1706 | 1706 |
| 1707 ZoneList<Expression*>* subexprs = expr->values(); | 1707 ZoneList<Expression*>* subexprs = expr->values(); |
| 1708 int length = subexprs->length(); | 1708 int length = subexprs->length(); |
| 1709 Handle<FixedArray> constant_elements = expr->constant_elements(); | 1709 Handle<FixedArray> constant_elements = expr->constant_elements(); |
| 1710 ASSERT_EQ(2, constant_elements->length()); | 1710 DCHECK_EQ(2, constant_elements->length()); |
| 1711 ElementsKind constant_elements_kind = | 1711 ElementsKind constant_elements_kind = |
| 1712 static_cast<ElementsKind>(Smi::cast(constant_elements->get(0))->value()); | 1712 static_cast<ElementsKind>(Smi::cast(constant_elements->get(0))->value()); |
| 1713 bool has_constant_fast_elements = | 1713 bool has_constant_fast_elements = |
| 1714 IsFastObjectElementsKind(constant_elements_kind); | 1714 IsFastObjectElementsKind(constant_elements_kind); |
| 1715 Handle<FixedArrayBase> constant_elements_values( | 1715 Handle<FixedArrayBase> constant_elements_values( |
| 1716 FixedArrayBase::cast(constant_elements->get(1))); | 1716 FixedArrayBase::cast(constant_elements->get(1))); |
| 1717 | 1717 |
| 1718 AllocationSiteMode allocation_site_mode = TRACK_ALLOCATION_SITE; | 1718 AllocationSiteMode allocation_site_mode = TRACK_ALLOCATION_SITE; |
| 1719 if (has_constant_fast_elements && !FLAG_allocation_site_pretenuring) { | 1719 if (has_constant_fast_elements && !FLAG_allocation_site_pretenuring) { |
| 1720 // If the only customer of allocation sites is transitioning, then | 1720 // If the only customer of allocation sites is transitioning, then |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1780 if (result_saved) { | 1780 if (result_saved) { |
| 1781 __ add(esp, Immediate(kPointerSize)); // literal index | 1781 __ add(esp, Immediate(kPointerSize)); // literal index |
| 1782 context()->PlugTOS(); | 1782 context()->PlugTOS(); |
| 1783 } else { | 1783 } else { |
| 1784 context()->Plug(eax); | 1784 context()->Plug(eax); |
| 1785 } | 1785 } |
| 1786 } | 1786 } |
| 1787 | 1787 |
| 1788 | 1788 |
| 1789 void FullCodeGenerator::VisitAssignment(Assignment* expr) { | 1789 void FullCodeGenerator::VisitAssignment(Assignment* expr) { |
| 1790 ASSERT(expr->target()->IsValidReferenceExpression()); | 1790 DCHECK(expr->target()->IsValidReferenceExpression()); |
| 1791 | 1791 |
| 1792 Comment cmnt(masm_, "[ Assignment"); | 1792 Comment cmnt(masm_, "[ Assignment"); |
| 1793 | 1793 |
| 1794 // Left-hand side can only be a property, a global or a (parameter or local) | 1794 // Left-hand side can only be a property, a global or a (parameter or local) |
| 1795 // slot. | 1795 // slot. |
| 1796 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; | 1796 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; |
| 1797 LhsKind assign_type = VARIABLE; | 1797 LhsKind assign_type = VARIABLE; |
| 1798 Property* property = expr->target()->AsProperty(); | 1798 Property* property = expr->target()->AsProperty(); |
| 1799 if (property != NULL) { | 1799 if (property != NULL) { |
| 1800 assign_type = (property->key()->IsPropertyName()) | 1800 assign_type = (property->key()->IsPropertyName()) |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1911 case Yield::INITIAL: { | 1911 case Yield::INITIAL: { |
| 1912 Label suspend, continuation, post_runtime, resume; | 1912 Label suspend, continuation, post_runtime, resume; |
| 1913 | 1913 |
| 1914 __ jmp(&suspend); | 1914 __ jmp(&suspend); |
| 1915 | 1915 |
| 1916 __ bind(&continuation); | 1916 __ bind(&continuation); |
| 1917 __ jmp(&resume); | 1917 __ jmp(&resume); |
| 1918 | 1918 |
| 1919 __ bind(&suspend); | 1919 __ bind(&suspend); |
| 1920 VisitForAccumulatorValue(expr->generator_object()); | 1920 VisitForAccumulatorValue(expr->generator_object()); |
| 1921 ASSERT(continuation.pos() > 0 && Smi::IsValid(continuation.pos())); | 1921 DCHECK(continuation.pos() > 0 && Smi::IsValid(continuation.pos())); |
| 1922 __ mov(FieldOperand(eax, JSGeneratorObject::kContinuationOffset), | 1922 __ mov(FieldOperand(eax, JSGeneratorObject::kContinuationOffset), |
| 1923 Immediate(Smi::FromInt(continuation.pos()))); | 1923 Immediate(Smi::FromInt(continuation.pos()))); |
| 1924 __ mov(FieldOperand(eax, JSGeneratorObject::kContextOffset), esi); | 1924 __ mov(FieldOperand(eax, JSGeneratorObject::kContextOffset), esi); |
| 1925 __ mov(ecx, esi); | 1925 __ mov(ecx, esi); |
| 1926 __ RecordWriteField(eax, JSGeneratorObject::kContextOffset, ecx, edx); | 1926 __ RecordWriteField(eax, JSGeneratorObject::kContextOffset, ecx, edx); |
| 1927 __ lea(ebx, Operand(ebp, StandardFrameConstants::kExpressionsOffset)); | 1927 __ lea(ebx, Operand(ebp, StandardFrameConstants::kExpressionsOffset)); |
| 1928 __ cmp(esp, ebx); | 1928 __ cmp(esp, ebx); |
| 1929 __ j(equal, &post_runtime); | 1929 __ j(equal, &post_runtime); |
| 1930 __ push(eax); // generator object | 1930 __ push(eax); // generator object |
| 1931 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); | 1931 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1985 __ PushTryHandler(StackHandler::CATCH, expr->index()); | 1985 __ PushTryHandler(StackHandler::CATCH, expr->index()); |
| 1986 const int handler_size = StackHandlerConstants::kSize; | 1986 const int handler_size = StackHandlerConstants::kSize; |
| 1987 __ push(eax); // result | 1987 __ push(eax); // result |
| 1988 __ jmp(&l_suspend); | 1988 __ jmp(&l_suspend); |
| 1989 __ bind(&l_continuation); | 1989 __ bind(&l_continuation); |
| 1990 __ jmp(&l_resume); | 1990 __ jmp(&l_resume); |
| 1991 __ bind(&l_suspend); | 1991 __ bind(&l_suspend); |
| 1992 const int generator_object_depth = kPointerSize + handler_size; | 1992 const int generator_object_depth = kPointerSize + handler_size; |
| 1993 __ mov(eax, Operand(esp, generator_object_depth)); | 1993 __ mov(eax, Operand(esp, generator_object_depth)); |
| 1994 __ push(eax); // g | 1994 __ push(eax); // g |
| 1995 ASSERT(l_continuation.pos() > 0 && Smi::IsValid(l_continuation.pos())); | 1995 DCHECK(l_continuation.pos() > 0 && Smi::IsValid(l_continuation.pos())); |
| 1996 __ mov(FieldOperand(eax, JSGeneratorObject::kContinuationOffset), | 1996 __ mov(FieldOperand(eax, JSGeneratorObject::kContinuationOffset), |
| 1997 Immediate(Smi::FromInt(l_continuation.pos()))); | 1997 Immediate(Smi::FromInt(l_continuation.pos()))); |
| 1998 __ mov(FieldOperand(eax, JSGeneratorObject::kContextOffset), esi); | 1998 __ mov(FieldOperand(eax, JSGeneratorObject::kContextOffset), esi); |
| 1999 __ mov(ecx, esi); | 1999 __ mov(ecx, esi); |
| 2000 __ RecordWriteField(eax, JSGeneratorObject::kContextOffset, ecx, edx); | 2000 __ RecordWriteField(eax, JSGeneratorObject::kContextOffset, ecx, edx); |
| 2001 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); | 2001 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); |
| 2002 __ mov(context_register(), | 2002 __ mov(context_register(), |
| 2003 Operand(ebp, StandardFrameConstants::kContextOffset)); | 2003 Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 2004 __ pop(eax); // result | 2004 __ pop(eax); // result |
| 2005 EmitReturnSequence(); | 2005 EmitReturnSequence(); |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2187 __ bind(&gc_required); | 2187 __ bind(&gc_required); |
| 2188 __ Push(Smi::FromInt(map->instance_size())); | 2188 __ Push(Smi::FromInt(map->instance_size())); |
| 2189 __ CallRuntime(Runtime::kAllocateInNewSpace, 1); | 2189 __ CallRuntime(Runtime::kAllocateInNewSpace, 1); |
| 2190 __ mov(context_register(), | 2190 __ mov(context_register(), |
| 2191 Operand(ebp, StandardFrameConstants::kContextOffset)); | 2191 Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 2192 | 2192 |
| 2193 __ bind(&allocated); | 2193 __ bind(&allocated); |
| 2194 __ mov(ebx, map); | 2194 __ mov(ebx, map); |
| 2195 __ pop(ecx); | 2195 __ pop(ecx); |
| 2196 __ mov(edx, isolate()->factory()->ToBoolean(done)); | 2196 __ mov(edx, isolate()->factory()->ToBoolean(done)); |
| 2197 ASSERT_EQ(map->instance_size(), 5 * kPointerSize); | 2197 DCHECK_EQ(map->instance_size(), 5 * kPointerSize); |
| 2198 __ mov(FieldOperand(eax, HeapObject::kMapOffset), ebx); | 2198 __ mov(FieldOperand(eax, HeapObject::kMapOffset), ebx); |
| 2199 __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), | 2199 __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), |
| 2200 isolate()->factory()->empty_fixed_array()); | 2200 isolate()->factory()->empty_fixed_array()); |
| 2201 __ mov(FieldOperand(eax, JSObject::kElementsOffset), | 2201 __ mov(FieldOperand(eax, JSObject::kElementsOffset), |
| 2202 isolate()->factory()->empty_fixed_array()); | 2202 isolate()->factory()->empty_fixed_array()); |
| 2203 __ mov(FieldOperand(eax, JSGeneratorObject::kResultValuePropertyOffset), ecx); | 2203 __ mov(FieldOperand(eax, JSGeneratorObject::kResultValuePropertyOffset), ecx); |
| 2204 __ mov(FieldOperand(eax, JSGeneratorObject::kResultDonePropertyOffset), edx); | 2204 __ mov(FieldOperand(eax, JSGeneratorObject::kResultDonePropertyOffset), edx); |
| 2205 | 2205 |
| 2206 // Only the value field needs a write barrier, as the other values are in the | 2206 // Only the value field needs a write barrier, as the other values are in the |
| 2207 // root set. | 2207 // root set. |
| 2208 __ RecordWriteField(eax, JSGeneratorObject::kResultValuePropertyOffset, | 2208 __ RecordWriteField(eax, JSGeneratorObject::kResultValuePropertyOffset, |
| 2209 ecx, edx); | 2209 ecx, edx); |
| 2210 } | 2210 } |
| 2211 | 2211 |
| 2212 | 2212 |
| 2213 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { | 2213 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { |
| 2214 SetSourcePosition(prop->position()); | 2214 SetSourcePosition(prop->position()); |
| 2215 Literal* key = prop->key()->AsLiteral(); | 2215 Literal* key = prop->key()->AsLiteral(); |
| 2216 ASSERT(!key->value()->IsSmi()); | 2216 DCHECK(!key->value()->IsSmi()); |
| 2217 __ mov(LoadIC::NameRegister(), Immediate(key->value())); | 2217 __ mov(LoadIC::NameRegister(), Immediate(key->value())); |
| 2218 if (FLAG_vector_ics) { | 2218 if (FLAG_vector_ics) { |
| 2219 __ mov(LoadIC::SlotRegister(), | 2219 __ mov(LoadIC::SlotRegister(), |
| 2220 Immediate(Smi::FromInt(prop->PropertyFeedbackSlot()))); | 2220 Immediate(Smi::FromInt(prop->PropertyFeedbackSlot()))); |
| 2221 CallLoadIC(NOT_CONTEXTUAL); | 2221 CallLoadIC(NOT_CONTEXTUAL); |
| 2222 } else { | 2222 } else { |
| 2223 CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId()); | 2223 CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId()); |
| 2224 } | 2224 } |
| 2225 } | 2225 } |
| 2226 | 2226 |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2339 __ pop(edx); | 2339 __ pop(edx); |
| 2340 BinaryOpICStub stub(isolate(), op, mode); | 2340 BinaryOpICStub stub(isolate(), op, mode); |
| 2341 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. | 2341 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. |
| 2342 CallIC(stub.GetCode(), expr->BinaryOperationFeedbackId()); | 2342 CallIC(stub.GetCode(), expr->BinaryOperationFeedbackId()); |
| 2343 patch_site.EmitPatchInfo(); | 2343 patch_site.EmitPatchInfo(); |
| 2344 context()->Plug(eax); | 2344 context()->Plug(eax); |
| 2345 } | 2345 } |
| 2346 | 2346 |
| 2347 | 2347 |
| 2348 void FullCodeGenerator::EmitAssignment(Expression* expr) { | 2348 void FullCodeGenerator::EmitAssignment(Expression* expr) { |
| 2349 ASSERT(expr->IsValidReferenceExpression()); | 2349 DCHECK(expr->IsValidReferenceExpression()); |
| 2350 | 2350 |
| 2351 // Left-hand side can only be a property, a global or a (parameter or local) | 2351 // Left-hand side can only be a property, a global or a (parameter or local) |
| 2352 // slot. | 2352 // slot. |
| 2353 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; | 2353 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; |
| 2354 LhsKind assign_type = VARIABLE; | 2354 LhsKind assign_type = VARIABLE; |
| 2355 Property* prop = expr->AsProperty(); | 2355 Property* prop = expr->AsProperty(); |
| 2356 if (prop != NULL) { | 2356 if (prop != NULL) { |
| 2357 assign_type = (prop->key()->IsPropertyName()) | 2357 assign_type = (prop->key()->IsPropertyName()) |
| 2358 ? NAMED_PROPERTY | 2358 ? NAMED_PROPERTY |
| 2359 : KEYED_PROPERTY; | 2359 : KEYED_PROPERTY; |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2407 void FullCodeGenerator::EmitVariableAssignment(Variable* var, | 2407 void FullCodeGenerator::EmitVariableAssignment(Variable* var, |
| 2408 Token::Value op) { | 2408 Token::Value op) { |
| 2409 if (var->IsUnallocated()) { | 2409 if (var->IsUnallocated()) { |
| 2410 // Global var, const, or let. | 2410 // Global var, const, or let. |
| 2411 __ mov(StoreIC::NameRegister(), var->name()); | 2411 __ mov(StoreIC::NameRegister(), var->name()); |
| 2412 __ mov(StoreIC::ReceiverRegister(), GlobalObjectOperand()); | 2412 __ mov(StoreIC::ReceiverRegister(), GlobalObjectOperand()); |
| 2413 CallStoreIC(); | 2413 CallStoreIC(); |
| 2414 | 2414 |
| 2415 } else if (op == Token::INIT_CONST_LEGACY) { | 2415 } else if (op == Token::INIT_CONST_LEGACY) { |
| 2416 // Const initializers need a write barrier. | 2416 // Const initializers need a write barrier. |
| 2417 ASSERT(!var->IsParameter()); // No const parameters. | 2417 DCHECK(!var->IsParameter()); // No const parameters. |
| 2418 if (var->IsLookupSlot()) { | 2418 if (var->IsLookupSlot()) { |
| 2419 __ push(eax); | 2419 __ push(eax); |
| 2420 __ push(esi); | 2420 __ push(esi); |
| 2421 __ push(Immediate(var->name())); | 2421 __ push(Immediate(var->name())); |
| 2422 __ CallRuntime(Runtime::kInitializeLegacyConstLookupSlot, 3); | 2422 __ CallRuntime(Runtime::kInitializeLegacyConstLookupSlot, 3); |
| 2423 } else { | 2423 } else { |
| 2424 ASSERT(var->IsStackLocal() || var->IsContextSlot()); | 2424 DCHECK(var->IsStackLocal() || var->IsContextSlot()); |
| 2425 Label skip; | 2425 Label skip; |
| 2426 MemOperand location = VarOperand(var, ecx); | 2426 MemOperand location = VarOperand(var, ecx); |
| 2427 __ mov(edx, location); | 2427 __ mov(edx, location); |
| 2428 __ cmp(edx, isolate()->factory()->the_hole_value()); | 2428 __ cmp(edx, isolate()->factory()->the_hole_value()); |
| 2429 __ j(not_equal, &skip, Label::kNear); | 2429 __ j(not_equal, &skip, Label::kNear); |
| 2430 EmitStoreToStackLocalOrContextSlot(var, location); | 2430 EmitStoreToStackLocalOrContextSlot(var, location); |
| 2431 __ bind(&skip); | 2431 __ bind(&skip); |
| 2432 } | 2432 } |
| 2433 | 2433 |
| 2434 } else if (var->mode() == LET && op != Token::INIT_LET) { | 2434 } else if (var->mode() == LET && op != Token::INIT_LET) { |
| 2435 // Non-initializing assignment to let variable needs a write barrier. | 2435 // Non-initializing assignment to let variable needs a write barrier. |
| 2436 ASSERT(!var->IsLookupSlot()); | 2436 DCHECK(!var->IsLookupSlot()); |
| 2437 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); | 2437 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
| 2438 Label assign; | 2438 Label assign; |
| 2439 MemOperand location = VarOperand(var, ecx); | 2439 MemOperand location = VarOperand(var, ecx); |
| 2440 __ mov(edx, location); | 2440 __ mov(edx, location); |
| 2441 __ cmp(edx, isolate()->factory()->the_hole_value()); | 2441 __ cmp(edx, isolate()->factory()->the_hole_value()); |
| 2442 __ j(not_equal, &assign, Label::kNear); | 2442 __ j(not_equal, &assign, Label::kNear); |
| 2443 __ push(Immediate(var->name())); | 2443 __ push(Immediate(var->name())); |
| 2444 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 2444 __ CallRuntime(Runtime::kThrowReferenceError, 1); |
| 2445 __ bind(&assign); | 2445 __ bind(&assign); |
| 2446 EmitStoreToStackLocalOrContextSlot(var, location); | 2446 EmitStoreToStackLocalOrContextSlot(var, location); |
| 2447 | 2447 |
| 2448 } else if (!var->is_const_mode() || op == Token::INIT_CONST) { | 2448 } else if (!var->is_const_mode() || op == Token::INIT_CONST) { |
| 2449 if (var->IsLookupSlot()) { | 2449 if (var->IsLookupSlot()) { |
| 2450 // Assignment to var. | 2450 // Assignment to var. |
| 2451 __ push(eax); // Value. | 2451 __ push(eax); // Value. |
| 2452 __ push(esi); // Context. | 2452 __ push(esi); // Context. |
| 2453 __ push(Immediate(var->name())); | 2453 __ push(Immediate(var->name())); |
| 2454 __ push(Immediate(Smi::FromInt(strict_mode()))); | 2454 __ push(Immediate(Smi::FromInt(strict_mode()))); |
| 2455 __ CallRuntime(Runtime::kStoreLookupSlot, 4); | 2455 __ CallRuntime(Runtime::kStoreLookupSlot, 4); |
| 2456 } else { | 2456 } else { |
| 2457 // Assignment to var or initializing assignment to let/const in harmony | 2457 // Assignment to var or initializing assignment to let/const in harmony |
| 2458 // mode. | 2458 // mode. |
| 2459 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); | 2459 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
| 2460 MemOperand location = VarOperand(var, ecx); | 2460 MemOperand location = VarOperand(var, ecx); |
| 2461 if (generate_debug_code_ && op == Token::INIT_LET) { | 2461 if (generate_debug_code_ && op == Token::INIT_LET) { |
| 2462 // Check for an uninitialized let binding. | 2462 // Check for an uninitialized let binding. |
| 2463 __ mov(edx, location); | 2463 __ mov(edx, location); |
| 2464 __ cmp(edx, isolate()->factory()->the_hole_value()); | 2464 __ cmp(edx, isolate()->factory()->the_hole_value()); |
| 2465 __ Check(equal, kLetBindingReInitialization); | 2465 __ Check(equal, kLetBindingReInitialization); |
| 2466 } | 2466 } |
| 2467 EmitStoreToStackLocalOrContextSlot(var, location); | 2467 EmitStoreToStackLocalOrContextSlot(var, location); |
| 2468 } | 2468 } |
| 2469 } | 2469 } |
| 2470 // Non-initializing assignments to consts are ignored. | 2470 // Non-initializing assignments to consts are ignored. |
| 2471 } | 2471 } |
| 2472 | 2472 |
| 2473 | 2473 |
| 2474 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { | 2474 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { |
| 2475 // Assignment to a property, using a named store IC. | 2475 // Assignment to a property, using a named store IC. |
| 2476 // eax : value | 2476 // eax : value |
| 2477 // esp[0] : receiver | 2477 // esp[0] : receiver |
| 2478 | 2478 |
| 2479 Property* prop = expr->target()->AsProperty(); | 2479 Property* prop = expr->target()->AsProperty(); |
| 2480 ASSERT(prop != NULL); | 2480 DCHECK(prop != NULL); |
| 2481 ASSERT(prop->key()->IsLiteral()); | 2481 DCHECK(prop->key()->IsLiteral()); |
| 2482 | 2482 |
| 2483 // Record source code position before IC call. | 2483 // Record source code position before IC call. |
| 2484 SetSourcePosition(expr->position()); | 2484 SetSourcePosition(expr->position()); |
| 2485 __ mov(StoreIC::NameRegister(), prop->key()->AsLiteral()->value()); | 2485 __ mov(StoreIC::NameRegister(), prop->key()->AsLiteral()->value()); |
| 2486 __ pop(StoreIC::ReceiverRegister()); | 2486 __ pop(StoreIC::ReceiverRegister()); |
| 2487 CallStoreIC(expr->AssignmentFeedbackId()); | 2487 CallStoreIC(expr->AssignmentFeedbackId()); |
| 2488 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 2488 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 2489 context()->Plug(eax); | 2489 context()->Plug(eax); |
| 2490 } | 2490 } |
| 2491 | 2491 |
| 2492 | 2492 |
| 2493 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { | 2493 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { |
| 2494 // Assignment to a property, using a keyed store IC. | 2494 // Assignment to a property, using a keyed store IC. |
| 2495 // eax : value | 2495 // eax : value |
| 2496 // esp[0] : key | 2496 // esp[0] : key |
| 2497 // esp[kPointerSize] : receiver | 2497 // esp[kPointerSize] : receiver |
| 2498 | 2498 |
| 2499 __ pop(KeyedStoreIC::NameRegister()); // Key. | 2499 __ pop(KeyedStoreIC::NameRegister()); // Key. |
| 2500 __ pop(KeyedStoreIC::ReceiverRegister()); | 2500 __ pop(KeyedStoreIC::ReceiverRegister()); |
| 2501 ASSERT(KeyedStoreIC::ValueRegister().is(eax)); | 2501 DCHECK(KeyedStoreIC::ValueRegister().is(eax)); |
| 2502 // Record source code position before IC call. | 2502 // Record source code position before IC call. |
| 2503 SetSourcePosition(expr->position()); | 2503 SetSourcePosition(expr->position()); |
| 2504 Handle<Code> ic = strict_mode() == SLOPPY | 2504 Handle<Code> ic = strict_mode() == SLOPPY |
| 2505 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 2505 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
| 2506 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 2506 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
| 2507 CallIC(ic, expr->AssignmentFeedbackId()); | 2507 CallIC(ic, expr->AssignmentFeedbackId()); |
| 2508 | 2508 |
| 2509 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 2509 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 2510 context()->Plug(eax); | 2510 context()->Plug(eax); |
| 2511 } | 2511 } |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2550 if (call_type == CallIC::FUNCTION) { | 2550 if (call_type == CallIC::FUNCTION) { |
| 2551 { StackValueContext context(this); | 2551 { StackValueContext context(this); |
| 2552 EmitVariableLoad(callee->AsVariableProxy()); | 2552 EmitVariableLoad(callee->AsVariableProxy()); |
| 2553 PrepareForBailout(callee, NO_REGISTERS); | 2553 PrepareForBailout(callee, NO_REGISTERS); |
| 2554 } | 2554 } |
| 2555 // Push undefined as receiver. This is patched in the method prologue if it | 2555 // Push undefined as receiver. This is patched in the method prologue if it |
| 2556 // is a sloppy mode method. | 2556 // is a sloppy mode method. |
| 2557 __ push(Immediate(isolate()->factory()->undefined_value())); | 2557 __ push(Immediate(isolate()->factory()->undefined_value())); |
| 2558 } else { | 2558 } else { |
| 2559 // Load the function from the receiver. | 2559 // Load the function from the receiver. |
| 2560 ASSERT(callee->IsProperty()); | 2560 DCHECK(callee->IsProperty()); |
| 2561 __ mov(LoadIC::ReceiverRegister(), Operand(esp, 0)); | 2561 __ mov(LoadIC::ReceiverRegister(), Operand(esp, 0)); |
| 2562 EmitNamedPropertyLoad(callee->AsProperty()); | 2562 EmitNamedPropertyLoad(callee->AsProperty()); |
| 2563 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); | 2563 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); |
| 2564 // Push the target function under the receiver. | 2564 // Push the target function under the receiver. |
| 2565 __ push(Operand(esp, 0)); | 2565 __ push(Operand(esp, 0)); |
| 2566 __ mov(Operand(esp, kPointerSize), eax); | 2566 __ mov(Operand(esp, kPointerSize), eax); |
| 2567 } | 2567 } |
| 2568 | 2568 |
| 2569 EmitCall(expr, call_type); | 2569 EmitCall(expr, call_type); |
| 2570 } | 2570 } |
| 2571 | 2571 |
| 2572 | 2572 |
| 2573 // Code common for calls using the IC. | 2573 // Code common for calls using the IC. |
| 2574 void FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr, | 2574 void FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr, |
| 2575 Expression* key) { | 2575 Expression* key) { |
| 2576 // Load the key. | 2576 // Load the key. |
| 2577 VisitForAccumulatorValue(key); | 2577 VisitForAccumulatorValue(key); |
| 2578 | 2578 |
| 2579 Expression* callee = expr->expression(); | 2579 Expression* callee = expr->expression(); |
| 2580 | 2580 |
| 2581 // Load the function from the receiver. | 2581 // Load the function from the receiver. |
| 2582 ASSERT(callee->IsProperty()); | 2582 DCHECK(callee->IsProperty()); |
| 2583 __ mov(LoadIC::ReceiverRegister(), Operand(esp, 0)); | 2583 __ mov(LoadIC::ReceiverRegister(), Operand(esp, 0)); |
| 2584 __ mov(LoadIC::NameRegister(), eax); | 2584 __ mov(LoadIC::NameRegister(), eax); |
| 2585 EmitKeyedPropertyLoad(callee->AsProperty()); | 2585 EmitKeyedPropertyLoad(callee->AsProperty()); |
| 2586 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); | 2586 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); |
| 2587 | 2587 |
| 2588 // Push the target function under the receiver. | 2588 // Push the target function under the receiver. |
| 2589 __ push(Operand(esp, 0)); | 2589 __ push(Operand(esp, 0)); |
| 2590 __ mov(Operand(esp, kPointerSize), eax); | 2590 __ mov(Operand(esp, kPointerSize), eax); |
| 2591 | 2591 |
| 2592 EmitCall(expr, CallIC::METHOD); | 2592 EmitCall(expr, CallIC::METHOD); |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2733 { PreservePositionScope scope(masm()->positions_recorder()); | 2733 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2734 VisitForStackValue(property->obj()); | 2734 VisitForStackValue(property->obj()); |
| 2735 } | 2735 } |
| 2736 if (property->key()->IsPropertyName()) { | 2736 if (property->key()->IsPropertyName()) { |
| 2737 EmitCallWithLoadIC(expr); | 2737 EmitCallWithLoadIC(expr); |
| 2738 } else { | 2738 } else { |
| 2739 EmitKeyedCallWithLoadIC(expr, property->key()); | 2739 EmitKeyedCallWithLoadIC(expr, property->key()); |
| 2740 } | 2740 } |
| 2741 | 2741 |
| 2742 } else { | 2742 } else { |
| 2743 ASSERT(call_type == Call::OTHER_CALL); | 2743 DCHECK(call_type == Call::OTHER_CALL); |
| 2744 // Call to an arbitrary expression not handled specially above. | 2744 // Call to an arbitrary expression not handled specially above. |
| 2745 { PreservePositionScope scope(masm()->positions_recorder()); | 2745 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2746 VisitForStackValue(callee); | 2746 VisitForStackValue(callee); |
| 2747 } | 2747 } |
| 2748 __ push(Immediate(isolate()->factory()->undefined_value())); | 2748 __ push(Immediate(isolate()->factory()->undefined_value())); |
| 2749 // Emit function call. | 2749 // Emit function call. |
| 2750 EmitCall(expr); | 2750 EmitCall(expr); |
| 2751 } | 2751 } |
| 2752 | 2752 |
| 2753 #ifdef DEBUG | 2753 #ifdef DEBUG |
| 2754 // RecordJSReturnSite should have been called. | 2754 // RecordJSReturnSite should have been called. |
| 2755 ASSERT(expr->return_is_recorded_); | 2755 DCHECK(expr->return_is_recorded_); |
| 2756 #endif | 2756 #endif |
| 2757 } | 2757 } |
| 2758 | 2758 |
| 2759 | 2759 |
| 2760 void FullCodeGenerator::VisitCallNew(CallNew* expr) { | 2760 void FullCodeGenerator::VisitCallNew(CallNew* expr) { |
| 2761 Comment cmnt(masm_, "[ CallNew"); | 2761 Comment cmnt(masm_, "[ CallNew"); |
| 2762 // According to ECMA-262, section 11.2.2, page 44, the function | 2762 // According to ECMA-262, section 11.2.2, page 44, the function |
| 2763 // expression in new calls must be evaluated before the | 2763 // expression in new calls must be evaluated before the |
| 2764 // arguments. | 2764 // arguments. |
| 2765 | 2765 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 2779 // constructor invocation. | 2779 // constructor invocation. |
| 2780 SetSourcePosition(expr->position()); | 2780 SetSourcePosition(expr->position()); |
| 2781 | 2781 |
| 2782 // Load function and argument count into edi and eax. | 2782 // Load function and argument count into edi and eax. |
| 2783 __ Move(eax, Immediate(arg_count)); | 2783 __ Move(eax, Immediate(arg_count)); |
| 2784 __ mov(edi, Operand(esp, arg_count * kPointerSize)); | 2784 __ mov(edi, Operand(esp, arg_count * kPointerSize)); |
| 2785 | 2785 |
| 2786 // Record call targets in unoptimized code. | 2786 // Record call targets in unoptimized code. |
| 2787 if (FLAG_pretenuring_call_new) { | 2787 if (FLAG_pretenuring_call_new) { |
| 2788 EnsureSlotContainsAllocationSite(expr->AllocationSiteFeedbackSlot()); | 2788 EnsureSlotContainsAllocationSite(expr->AllocationSiteFeedbackSlot()); |
| 2789 ASSERT(expr->AllocationSiteFeedbackSlot() == | 2789 DCHECK(expr->AllocationSiteFeedbackSlot() == |
| 2790 expr->CallNewFeedbackSlot() + 1); | 2790 expr->CallNewFeedbackSlot() + 1); |
| 2791 } | 2791 } |
| 2792 | 2792 |
| 2793 __ LoadHeapObject(ebx, FeedbackVector()); | 2793 __ LoadHeapObject(ebx, FeedbackVector()); |
| 2794 __ mov(edx, Immediate(Smi::FromInt(expr->CallNewFeedbackSlot()))); | 2794 __ mov(edx, Immediate(Smi::FromInt(expr->CallNewFeedbackSlot()))); |
| 2795 | 2795 |
| 2796 CallConstructStub stub(isolate(), RECORD_CONSTRUCTOR_TARGET); | 2796 CallConstructStub stub(isolate(), RECORD_CONSTRUCTOR_TARGET); |
| 2797 __ call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL); | 2797 __ call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL); |
| 2798 PrepareForBailoutForId(expr->ReturnId(), TOS_REG); | 2798 PrepareForBailoutForId(expr->ReturnId(), TOS_REG); |
| 2799 context()->Plug(eax); | 2799 context()->Plug(eax); |
| 2800 } | 2800 } |
| 2801 | 2801 |
| 2802 | 2802 |
| 2803 void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) { | 2803 void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) { |
| 2804 ZoneList<Expression*>* args = expr->arguments(); | 2804 ZoneList<Expression*>* args = expr->arguments(); |
| 2805 ASSERT(args->length() == 1); | 2805 DCHECK(args->length() == 1); |
| 2806 | 2806 |
| 2807 VisitForAccumulatorValue(args->at(0)); | 2807 VisitForAccumulatorValue(args->at(0)); |
| 2808 | 2808 |
| 2809 Label materialize_true, materialize_false; | 2809 Label materialize_true, materialize_false; |
| 2810 Label* if_true = NULL; | 2810 Label* if_true = NULL; |
| 2811 Label* if_false = NULL; | 2811 Label* if_false = NULL; |
| 2812 Label* fall_through = NULL; | 2812 Label* fall_through = NULL; |
| 2813 context()->PrepareTest(&materialize_true, &materialize_false, | 2813 context()->PrepareTest(&materialize_true, &materialize_false, |
| 2814 &if_true, &if_false, &fall_through); | 2814 &if_true, &if_false, &fall_through); |
| 2815 | 2815 |
| 2816 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 2816 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
| 2817 __ test(eax, Immediate(kSmiTagMask)); | 2817 __ test(eax, Immediate(kSmiTagMask)); |
| 2818 Split(zero, if_true, if_false, fall_through); | 2818 Split(zero, if_true, if_false, fall_through); |
| 2819 | 2819 |
| 2820 context()->Plug(if_true, if_false); | 2820 context()->Plug(if_true, if_false); |
| 2821 } | 2821 } |
| 2822 | 2822 |
| 2823 | 2823 |
| 2824 void FullCodeGenerator::EmitIsNonNegativeSmi(CallRuntime* expr) { | 2824 void FullCodeGenerator::EmitIsNonNegativeSmi(CallRuntime* expr) { |
| 2825 ZoneList<Expression*>* args = expr->arguments(); | 2825 ZoneList<Expression*>* args = expr->arguments(); |
| 2826 ASSERT(args->length() == 1); | 2826 DCHECK(args->length() == 1); |
| 2827 | 2827 |
| 2828 VisitForAccumulatorValue(args->at(0)); | 2828 VisitForAccumulatorValue(args->at(0)); |
| 2829 | 2829 |
| 2830 Label materialize_true, materialize_false; | 2830 Label materialize_true, materialize_false; |
| 2831 Label* if_true = NULL; | 2831 Label* if_true = NULL; |
| 2832 Label* if_false = NULL; | 2832 Label* if_false = NULL; |
| 2833 Label* fall_through = NULL; | 2833 Label* fall_through = NULL; |
| 2834 context()->PrepareTest(&materialize_true, &materialize_false, | 2834 context()->PrepareTest(&materialize_true, &materialize_false, |
| 2835 &if_true, &if_false, &fall_through); | 2835 &if_true, &if_false, &fall_through); |
| 2836 | 2836 |
| 2837 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 2837 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
| 2838 __ test(eax, Immediate(kSmiTagMask | 0x80000000)); | 2838 __ test(eax, Immediate(kSmiTagMask | 0x80000000)); |
| 2839 Split(zero, if_true, if_false, fall_through); | 2839 Split(zero, if_true, if_false, fall_through); |
| 2840 | 2840 |
| 2841 context()->Plug(if_true, if_false); | 2841 context()->Plug(if_true, if_false); |
| 2842 } | 2842 } |
| 2843 | 2843 |
| 2844 | 2844 |
| 2845 void FullCodeGenerator::EmitIsObject(CallRuntime* expr) { | 2845 void FullCodeGenerator::EmitIsObject(CallRuntime* expr) { |
| 2846 ZoneList<Expression*>* args = expr->arguments(); | 2846 ZoneList<Expression*>* args = expr->arguments(); |
| 2847 ASSERT(args->length() == 1); | 2847 DCHECK(args->length() == 1); |
| 2848 | 2848 |
| 2849 VisitForAccumulatorValue(args->at(0)); | 2849 VisitForAccumulatorValue(args->at(0)); |
| 2850 | 2850 |
| 2851 Label materialize_true, materialize_false; | 2851 Label materialize_true, materialize_false; |
| 2852 Label* if_true = NULL; | 2852 Label* if_true = NULL; |
| 2853 Label* if_false = NULL; | 2853 Label* if_false = NULL; |
| 2854 Label* fall_through = NULL; | 2854 Label* fall_through = NULL; |
| 2855 context()->PrepareTest(&materialize_true, &materialize_false, | 2855 context()->PrepareTest(&materialize_true, &materialize_false, |
| 2856 &if_true, &if_false, &fall_through); | 2856 &if_true, &if_false, &fall_through); |
| 2857 | 2857 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 2869 __ cmp(ecx, LAST_NONCALLABLE_SPEC_OBJECT_TYPE); | 2869 __ cmp(ecx, LAST_NONCALLABLE_SPEC_OBJECT_TYPE); |
| 2870 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 2870 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
| 2871 Split(below_equal, if_true, if_false, fall_through); | 2871 Split(below_equal, if_true, if_false, fall_through); |
| 2872 | 2872 |
| 2873 context()->Plug(if_true, if_false); | 2873 context()->Plug(if_true, if_false); |
| 2874 } | 2874 } |
| 2875 | 2875 |
| 2876 | 2876 |
| 2877 void FullCodeGenerator::EmitIsSpecObject(CallRuntime* expr) { | 2877 void FullCodeGenerator::EmitIsSpecObject(CallRuntime* expr) { |
| 2878 ZoneList<Expression*>* args = expr->arguments(); | 2878 ZoneList<Expression*>* args = expr->arguments(); |
| 2879 ASSERT(args->length() == 1); | 2879 DCHECK(args->length() == 1); |
| 2880 | 2880 |
| 2881 VisitForAccumulatorValue(args->at(0)); | 2881 VisitForAccumulatorValue(args->at(0)); |
| 2882 | 2882 |
| 2883 Label materialize_true, materialize_false; | 2883 Label materialize_true, materialize_false; |
| 2884 Label* if_true = NULL; | 2884 Label* if_true = NULL; |
| 2885 Label* if_false = NULL; | 2885 Label* if_false = NULL; |
| 2886 Label* fall_through = NULL; | 2886 Label* fall_through = NULL; |
| 2887 context()->PrepareTest(&materialize_true, &materialize_false, | 2887 context()->PrepareTest(&materialize_true, &materialize_false, |
| 2888 &if_true, &if_false, &fall_through); | 2888 &if_true, &if_false, &fall_through); |
| 2889 | 2889 |
| 2890 __ JumpIfSmi(eax, if_false); | 2890 __ JumpIfSmi(eax, if_false); |
| 2891 __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ebx); | 2891 __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ebx); |
| 2892 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 2892 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
| 2893 Split(above_equal, if_true, if_false, fall_through); | 2893 Split(above_equal, if_true, if_false, fall_through); |
| 2894 | 2894 |
| 2895 context()->Plug(if_true, if_false); | 2895 context()->Plug(if_true, if_false); |
| 2896 } | 2896 } |
| 2897 | 2897 |
| 2898 | 2898 |
| 2899 void FullCodeGenerator::EmitIsUndetectableObject(CallRuntime* expr) { | 2899 void FullCodeGenerator::EmitIsUndetectableObject(CallRuntime* expr) { |
| 2900 ZoneList<Expression*>* args = expr->arguments(); | 2900 ZoneList<Expression*>* args = expr->arguments(); |
| 2901 ASSERT(args->length() == 1); | 2901 DCHECK(args->length() == 1); |
| 2902 | 2902 |
| 2903 VisitForAccumulatorValue(args->at(0)); | 2903 VisitForAccumulatorValue(args->at(0)); |
| 2904 | 2904 |
| 2905 Label materialize_true, materialize_false; | 2905 Label materialize_true, materialize_false; |
| 2906 Label* if_true = NULL; | 2906 Label* if_true = NULL; |
| 2907 Label* if_false = NULL; | 2907 Label* if_false = NULL; |
| 2908 Label* fall_through = NULL; | 2908 Label* fall_through = NULL; |
| 2909 context()->PrepareTest(&materialize_true, &materialize_false, | 2909 context()->PrepareTest(&materialize_true, &materialize_false, |
| 2910 &if_true, &if_false, &fall_through); | 2910 &if_true, &if_false, &fall_through); |
| 2911 | 2911 |
| 2912 __ JumpIfSmi(eax, if_false); | 2912 __ JumpIfSmi(eax, if_false); |
| 2913 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); | 2913 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); |
| 2914 __ movzx_b(ebx, FieldOperand(ebx, Map::kBitFieldOffset)); | 2914 __ movzx_b(ebx, FieldOperand(ebx, Map::kBitFieldOffset)); |
| 2915 __ test(ebx, Immediate(1 << Map::kIsUndetectable)); | 2915 __ test(ebx, Immediate(1 << Map::kIsUndetectable)); |
| 2916 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 2916 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
| 2917 Split(not_zero, if_true, if_false, fall_through); | 2917 Split(not_zero, if_true, if_false, fall_through); |
| 2918 | 2918 |
| 2919 context()->Plug(if_true, if_false); | 2919 context()->Plug(if_true, if_false); |
| 2920 } | 2920 } |
| 2921 | 2921 |
| 2922 | 2922 |
| 2923 void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf( | 2923 void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf( |
| 2924 CallRuntime* expr) { | 2924 CallRuntime* expr) { |
| 2925 ZoneList<Expression*>* args = expr->arguments(); | 2925 ZoneList<Expression*>* args = expr->arguments(); |
| 2926 ASSERT(args->length() == 1); | 2926 DCHECK(args->length() == 1); |
| 2927 | 2927 |
| 2928 VisitForAccumulatorValue(args->at(0)); | 2928 VisitForAccumulatorValue(args->at(0)); |
| 2929 | 2929 |
| 2930 Label materialize_true, materialize_false, skip_lookup; | 2930 Label materialize_true, materialize_false, skip_lookup; |
| 2931 Label* if_true = NULL; | 2931 Label* if_true = NULL; |
| 2932 Label* if_false = NULL; | 2932 Label* if_false = NULL; |
| 2933 Label* fall_through = NULL; | 2933 Label* fall_through = NULL; |
| 2934 context()->PrepareTest(&materialize_true, &materialize_false, | 2934 context()->PrepareTest(&materialize_true, &materialize_false, |
| 2935 &if_true, &if_false, &fall_through); | 2935 &if_true, &if_false, &fall_through); |
| 2936 | 2936 |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3006 Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX)); | 3006 Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX)); |
| 3007 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 3007 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
| 3008 Split(equal, if_true, if_false, fall_through); | 3008 Split(equal, if_true, if_false, fall_through); |
| 3009 | 3009 |
| 3010 context()->Plug(if_true, if_false); | 3010 context()->Plug(if_true, if_false); |
| 3011 } | 3011 } |
| 3012 | 3012 |
| 3013 | 3013 |
| 3014 void FullCodeGenerator::EmitIsFunction(CallRuntime* expr) { | 3014 void FullCodeGenerator::EmitIsFunction(CallRuntime* expr) { |
| 3015 ZoneList<Expression*>* args = expr->arguments(); | 3015 ZoneList<Expression*>* args = expr->arguments(); |
| 3016 ASSERT(args->length() == 1); | 3016 DCHECK(args->length() == 1); |
| 3017 | 3017 |
| 3018 VisitForAccumulatorValue(args->at(0)); | 3018 VisitForAccumulatorValue(args->at(0)); |
| 3019 | 3019 |
| 3020 Label materialize_true, materialize_false; | 3020 Label materialize_true, materialize_false; |
| 3021 Label* if_true = NULL; | 3021 Label* if_true = NULL; |
| 3022 Label* if_false = NULL; | 3022 Label* if_false = NULL; |
| 3023 Label* fall_through = NULL; | 3023 Label* fall_through = NULL; |
| 3024 context()->PrepareTest(&materialize_true, &materialize_false, | 3024 context()->PrepareTest(&materialize_true, &materialize_false, |
| 3025 &if_true, &if_false, &fall_through); | 3025 &if_true, &if_false, &fall_through); |
| 3026 | 3026 |
| 3027 __ JumpIfSmi(eax, if_false); | 3027 __ JumpIfSmi(eax, if_false); |
| 3028 __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx); | 3028 __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx); |
| 3029 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 3029 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
| 3030 Split(equal, if_true, if_false, fall_through); | 3030 Split(equal, if_true, if_false, fall_through); |
| 3031 | 3031 |
| 3032 context()->Plug(if_true, if_false); | 3032 context()->Plug(if_true, if_false); |
| 3033 } | 3033 } |
| 3034 | 3034 |
| 3035 | 3035 |
| 3036 void FullCodeGenerator::EmitIsMinusZero(CallRuntime* expr) { | 3036 void FullCodeGenerator::EmitIsMinusZero(CallRuntime* expr) { |
| 3037 ZoneList<Expression*>* args = expr->arguments(); | 3037 ZoneList<Expression*>* args = expr->arguments(); |
| 3038 ASSERT(args->length() == 1); | 3038 DCHECK(args->length() == 1); |
| 3039 | 3039 |
| 3040 VisitForAccumulatorValue(args->at(0)); | 3040 VisitForAccumulatorValue(args->at(0)); |
| 3041 | 3041 |
| 3042 Label materialize_true, materialize_false; | 3042 Label materialize_true, materialize_false; |
| 3043 Label* if_true = NULL; | 3043 Label* if_true = NULL; |
| 3044 Label* if_false = NULL; | 3044 Label* if_false = NULL; |
| 3045 Label* fall_through = NULL; | 3045 Label* fall_through = NULL; |
| 3046 context()->PrepareTest(&materialize_true, &materialize_false, | 3046 context()->PrepareTest(&materialize_true, &materialize_false, |
| 3047 &if_true, &if_false, &fall_through); | 3047 &if_true, &if_false, &fall_through); |
| 3048 | 3048 |
| 3049 Handle<Map> map = masm()->isolate()->factory()->heap_number_map(); | 3049 Handle<Map> map = masm()->isolate()->factory()->heap_number_map(); |
| 3050 __ CheckMap(eax, map, if_false, DO_SMI_CHECK); | 3050 __ CheckMap(eax, map, if_false, DO_SMI_CHECK); |
| 3051 // Check if the exponent half is 0x80000000. Comparing against 1 and | 3051 // Check if the exponent half is 0x80000000. Comparing against 1 and |
| 3052 // checking for overflow is the shortest possible encoding. | 3052 // checking for overflow is the shortest possible encoding. |
| 3053 __ cmp(FieldOperand(eax, HeapNumber::kExponentOffset), Immediate(0x1)); | 3053 __ cmp(FieldOperand(eax, HeapNumber::kExponentOffset), Immediate(0x1)); |
| 3054 __ j(no_overflow, if_false); | 3054 __ j(no_overflow, if_false); |
| 3055 __ cmp(FieldOperand(eax, HeapNumber::kMantissaOffset), Immediate(0x0)); | 3055 __ cmp(FieldOperand(eax, HeapNumber::kMantissaOffset), Immediate(0x0)); |
| 3056 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 3056 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
| 3057 Split(equal, if_true, if_false, fall_through); | 3057 Split(equal, if_true, if_false, fall_through); |
| 3058 | 3058 |
| 3059 context()->Plug(if_true, if_false); | 3059 context()->Plug(if_true, if_false); |
| 3060 } | 3060 } |
| 3061 | 3061 |
| 3062 | 3062 |
| 3063 | 3063 |
| 3064 void FullCodeGenerator::EmitIsArray(CallRuntime* expr) { | 3064 void FullCodeGenerator::EmitIsArray(CallRuntime* expr) { |
| 3065 ZoneList<Expression*>* args = expr->arguments(); | 3065 ZoneList<Expression*>* args = expr->arguments(); |
| 3066 ASSERT(args->length() == 1); | 3066 DCHECK(args->length() == 1); |
| 3067 | 3067 |
| 3068 VisitForAccumulatorValue(args->at(0)); | 3068 VisitForAccumulatorValue(args->at(0)); |
| 3069 | 3069 |
| 3070 Label materialize_true, materialize_false; | 3070 Label materialize_true, materialize_false; |
| 3071 Label* if_true = NULL; | 3071 Label* if_true = NULL; |
| 3072 Label* if_false = NULL; | 3072 Label* if_false = NULL; |
| 3073 Label* fall_through = NULL; | 3073 Label* fall_through = NULL; |
| 3074 context()->PrepareTest(&materialize_true, &materialize_false, | 3074 context()->PrepareTest(&materialize_true, &materialize_false, |
| 3075 &if_true, &if_false, &fall_through); | 3075 &if_true, &if_false, &fall_through); |
| 3076 | 3076 |
| 3077 __ JumpIfSmi(eax, if_false); | 3077 __ JumpIfSmi(eax, if_false); |
| 3078 __ CmpObjectType(eax, JS_ARRAY_TYPE, ebx); | 3078 __ CmpObjectType(eax, JS_ARRAY_TYPE, ebx); |
| 3079 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 3079 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
| 3080 Split(equal, if_true, if_false, fall_through); | 3080 Split(equal, if_true, if_false, fall_through); |
| 3081 | 3081 |
| 3082 context()->Plug(if_true, if_false); | 3082 context()->Plug(if_true, if_false); |
| 3083 } | 3083 } |
| 3084 | 3084 |
| 3085 | 3085 |
| 3086 void FullCodeGenerator::EmitIsRegExp(CallRuntime* expr) { | 3086 void FullCodeGenerator::EmitIsRegExp(CallRuntime* expr) { |
| 3087 ZoneList<Expression*>* args = expr->arguments(); | 3087 ZoneList<Expression*>* args = expr->arguments(); |
| 3088 ASSERT(args->length() == 1); | 3088 DCHECK(args->length() == 1); |
| 3089 | 3089 |
| 3090 VisitForAccumulatorValue(args->at(0)); | 3090 VisitForAccumulatorValue(args->at(0)); |
| 3091 | 3091 |
| 3092 Label materialize_true, materialize_false; | 3092 Label materialize_true, materialize_false; |
| 3093 Label* if_true = NULL; | 3093 Label* if_true = NULL; |
| 3094 Label* if_false = NULL; | 3094 Label* if_false = NULL; |
| 3095 Label* fall_through = NULL; | 3095 Label* fall_through = NULL; |
| 3096 context()->PrepareTest(&materialize_true, &materialize_false, | 3096 context()->PrepareTest(&materialize_true, &materialize_false, |
| 3097 &if_true, &if_false, &fall_through); | 3097 &if_true, &if_false, &fall_through); |
| 3098 | 3098 |
| 3099 __ JumpIfSmi(eax, if_false); | 3099 __ JumpIfSmi(eax, if_false); |
| 3100 __ CmpObjectType(eax, JS_REGEXP_TYPE, ebx); | 3100 __ CmpObjectType(eax, JS_REGEXP_TYPE, ebx); |
| 3101 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 3101 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
| 3102 Split(equal, if_true, if_false, fall_through); | 3102 Split(equal, if_true, if_false, fall_through); |
| 3103 | 3103 |
| 3104 context()->Plug(if_true, if_false); | 3104 context()->Plug(if_true, if_false); |
| 3105 } | 3105 } |
| 3106 | 3106 |
| 3107 | 3107 |
| 3108 | 3108 |
| 3109 void FullCodeGenerator::EmitIsConstructCall(CallRuntime* expr) { | 3109 void FullCodeGenerator::EmitIsConstructCall(CallRuntime* expr) { |
| 3110 ASSERT(expr->arguments()->length() == 0); | 3110 DCHECK(expr->arguments()->length() == 0); |
| 3111 | 3111 |
| 3112 Label materialize_true, materialize_false; | 3112 Label materialize_true, materialize_false; |
| 3113 Label* if_true = NULL; | 3113 Label* if_true = NULL; |
| 3114 Label* if_false = NULL; | 3114 Label* if_false = NULL; |
| 3115 Label* fall_through = NULL; | 3115 Label* fall_through = NULL; |
| 3116 context()->PrepareTest(&materialize_true, &materialize_false, | 3116 context()->PrepareTest(&materialize_true, &materialize_false, |
| 3117 &if_true, &if_false, &fall_through); | 3117 &if_true, &if_false, &fall_through); |
| 3118 | 3118 |
| 3119 // Get the frame pointer for the calling frame. | 3119 // Get the frame pointer for the calling frame. |
| 3120 __ mov(eax, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); | 3120 __ mov(eax, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 3132 Immediate(Smi::FromInt(StackFrame::CONSTRUCT))); | 3132 Immediate(Smi::FromInt(StackFrame::CONSTRUCT))); |
| 3133 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 3133 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
| 3134 Split(equal, if_true, if_false, fall_through); | 3134 Split(equal, if_true, if_false, fall_through); |
| 3135 | 3135 |
| 3136 context()->Plug(if_true, if_false); | 3136 context()->Plug(if_true, if_false); |
| 3137 } | 3137 } |
| 3138 | 3138 |
| 3139 | 3139 |
| 3140 void FullCodeGenerator::EmitObjectEquals(CallRuntime* expr) { | 3140 void FullCodeGenerator::EmitObjectEquals(CallRuntime* expr) { |
| 3141 ZoneList<Expression*>* args = expr->arguments(); | 3141 ZoneList<Expression*>* args = expr->arguments(); |
| 3142 ASSERT(args->length() == 2); | 3142 DCHECK(args->length() == 2); |
| 3143 | 3143 |
| 3144 // Load the two objects into registers and perform the comparison. | 3144 // Load the two objects into registers and perform the comparison. |
| 3145 VisitForStackValue(args->at(0)); | 3145 VisitForStackValue(args->at(0)); |
| 3146 VisitForAccumulatorValue(args->at(1)); | 3146 VisitForAccumulatorValue(args->at(1)); |
| 3147 | 3147 |
| 3148 Label materialize_true, materialize_false; | 3148 Label materialize_true, materialize_false; |
| 3149 Label* if_true = NULL; | 3149 Label* if_true = NULL; |
| 3150 Label* if_false = NULL; | 3150 Label* if_false = NULL; |
| 3151 Label* fall_through = NULL; | 3151 Label* fall_through = NULL; |
| 3152 context()->PrepareTest(&materialize_true, &materialize_false, | 3152 context()->PrepareTest(&materialize_true, &materialize_false, |
| 3153 &if_true, &if_false, &fall_through); | 3153 &if_true, &if_false, &fall_through); |
| 3154 | 3154 |
| 3155 __ pop(ebx); | 3155 __ pop(ebx); |
| 3156 __ cmp(eax, ebx); | 3156 __ cmp(eax, ebx); |
| 3157 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 3157 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
| 3158 Split(equal, if_true, if_false, fall_through); | 3158 Split(equal, if_true, if_false, fall_through); |
| 3159 | 3159 |
| 3160 context()->Plug(if_true, if_false); | 3160 context()->Plug(if_true, if_false); |
| 3161 } | 3161 } |
| 3162 | 3162 |
| 3163 | 3163 |
| 3164 void FullCodeGenerator::EmitArguments(CallRuntime* expr) { | 3164 void FullCodeGenerator::EmitArguments(CallRuntime* expr) { |
| 3165 ZoneList<Expression*>* args = expr->arguments(); | 3165 ZoneList<Expression*>* args = expr->arguments(); |
| 3166 ASSERT(args->length() == 1); | 3166 DCHECK(args->length() == 1); |
| 3167 | 3167 |
| 3168 // ArgumentsAccessStub expects the key in edx and the formal | 3168 // ArgumentsAccessStub expects the key in edx and the formal |
| 3169 // parameter count in eax. | 3169 // parameter count in eax. |
| 3170 VisitForAccumulatorValue(args->at(0)); | 3170 VisitForAccumulatorValue(args->at(0)); |
| 3171 __ mov(edx, eax); | 3171 __ mov(edx, eax); |
| 3172 __ Move(eax, Immediate(Smi::FromInt(info_->scope()->num_parameters()))); | 3172 __ Move(eax, Immediate(Smi::FromInt(info_->scope()->num_parameters()))); |
| 3173 ArgumentsAccessStub stub(isolate(), ArgumentsAccessStub::READ_ELEMENT); | 3173 ArgumentsAccessStub stub(isolate(), ArgumentsAccessStub::READ_ELEMENT); |
| 3174 __ CallStub(&stub); | 3174 __ CallStub(&stub); |
| 3175 context()->Plug(eax); | 3175 context()->Plug(eax); |
| 3176 } | 3176 } |
| 3177 | 3177 |
| 3178 | 3178 |
| 3179 void FullCodeGenerator::EmitArgumentsLength(CallRuntime* expr) { | 3179 void FullCodeGenerator::EmitArgumentsLength(CallRuntime* expr) { |
| 3180 ASSERT(expr->arguments()->length() == 0); | 3180 DCHECK(expr->arguments()->length() == 0); |
| 3181 | 3181 |
| 3182 Label exit; | 3182 Label exit; |
| 3183 // Get the number of formal parameters. | 3183 // Get the number of formal parameters. |
| 3184 __ Move(eax, Immediate(Smi::FromInt(info_->scope()->num_parameters()))); | 3184 __ Move(eax, Immediate(Smi::FromInt(info_->scope()->num_parameters()))); |
| 3185 | 3185 |
| 3186 // Check if the calling frame is an arguments adaptor frame. | 3186 // Check if the calling frame is an arguments adaptor frame. |
| 3187 __ mov(ebx, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); | 3187 __ mov(ebx, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); |
| 3188 __ cmp(Operand(ebx, StandardFrameConstants::kContextOffset), | 3188 __ cmp(Operand(ebx, StandardFrameConstants::kContextOffset), |
| 3189 Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | 3189 Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); |
| 3190 __ j(not_equal, &exit); | 3190 __ j(not_equal, &exit); |
| 3191 | 3191 |
| 3192 // Arguments adaptor case: Read the arguments length from the | 3192 // Arguments adaptor case: Read the arguments length from the |
| 3193 // adaptor frame. | 3193 // adaptor frame. |
| 3194 __ mov(eax, Operand(ebx, ArgumentsAdaptorFrameConstants::kLengthOffset)); | 3194 __ mov(eax, Operand(ebx, ArgumentsAdaptorFrameConstants::kLengthOffset)); |
| 3195 | 3195 |
| 3196 __ bind(&exit); | 3196 __ bind(&exit); |
| 3197 __ AssertSmi(eax); | 3197 __ AssertSmi(eax); |
| 3198 context()->Plug(eax); | 3198 context()->Plug(eax); |
| 3199 } | 3199 } |
| 3200 | 3200 |
| 3201 | 3201 |
| 3202 void FullCodeGenerator::EmitClassOf(CallRuntime* expr) { | 3202 void FullCodeGenerator::EmitClassOf(CallRuntime* expr) { |
| 3203 ZoneList<Expression*>* args = expr->arguments(); | 3203 ZoneList<Expression*>* args = expr->arguments(); |
| 3204 ASSERT(args->length() == 1); | 3204 DCHECK(args->length() == 1); |
| 3205 Label done, null, function, non_function_constructor; | 3205 Label done, null, function, non_function_constructor; |
| 3206 | 3206 |
| 3207 VisitForAccumulatorValue(args->at(0)); | 3207 VisitForAccumulatorValue(args->at(0)); |
| 3208 | 3208 |
| 3209 // If the object is a smi, we return null. | 3209 // If the object is a smi, we return null. |
| 3210 __ JumpIfSmi(eax, &null); | 3210 __ JumpIfSmi(eax, &null); |
| 3211 | 3211 |
| 3212 // Check that the object is a JS object but take special care of JS | 3212 // Check that the object is a JS object but take special care of JS |
| 3213 // functions to make sure they have 'Function' as their class. | 3213 // functions to make sure they have 'Function' as their class. |
| 3214 // Assume that there are only two callable types, and one of them is at | 3214 // 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... |
| 3257 __ bind(&done); | 3257 __ bind(&done); |
| 3258 | 3258 |
| 3259 context()->Plug(eax); | 3259 context()->Plug(eax); |
| 3260 } | 3260 } |
| 3261 | 3261 |
| 3262 | 3262 |
| 3263 void FullCodeGenerator::EmitSubString(CallRuntime* expr) { | 3263 void FullCodeGenerator::EmitSubString(CallRuntime* expr) { |
| 3264 // Load the arguments on the stack and call the stub. | 3264 // Load the arguments on the stack and call the stub. |
| 3265 SubStringStub stub(isolate()); | 3265 SubStringStub stub(isolate()); |
| 3266 ZoneList<Expression*>* args = expr->arguments(); | 3266 ZoneList<Expression*>* args = expr->arguments(); |
| 3267 ASSERT(args->length() == 3); | 3267 DCHECK(args->length() == 3); |
| 3268 VisitForStackValue(args->at(0)); | 3268 VisitForStackValue(args->at(0)); |
| 3269 VisitForStackValue(args->at(1)); | 3269 VisitForStackValue(args->at(1)); |
| 3270 VisitForStackValue(args->at(2)); | 3270 VisitForStackValue(args->at(2)); |
| 3271 __ CallStub(&stub); | 3271 __ CallStub(&stub); |
| 3272 context()->Plug(eax); | 3272 context()->Plug(eax); |
| 3273 } | 3273 } |
| 3274 | 3274 |
| 3275 | 3275 |
| 3276 void FullCodeGenerator::EmitRegExpExec(CallRuntime* expr) { | 3276 void FullCodeGenerator::EmitRegExpExec(CallRuntime* expr) { |
| 3277 // Load the arguments on the stack and call the stub. | 3277 // Load the arguments on the stack and call the stub. |
| 3278 RegExpExecStub stub(isolate()); | 3278 RegExpExecStub stub(isolate()); |
| 3279 ZoneList<Expression*>* args = expr->arguments(); | 3279 ZoneList<Expression*>* args = expr->arguments(); |
| 3280 ASSERT(args->length() == 4); | 3280 DCHECK(args->length() == 4); |
| 3281 VisitForStackValue(args->at(0)); | 3281 VisitForStackValue(args->at(0)); |
| 3282 VisitForStackValue(args->at(1)); | 3282 VisitForStackValue(args->at(1)); |
| 3283 VisitForStackValue(args->at(2)); | 3283 VisitForStackValue(args->at(2)); |
| 3284 VisitForStackValue(args->at(3)); | 3284 VisitForStackValue(args->at(3)); |
| 3285 __ CallStub(&stub); | 3285 __ CallStub(&stub); |
| 3286 context()->Plug(eax); | 3286 context()->Plug(eax); |
| 3287 } | 3287 } |
| 3288 | 3288 |
| 3289 | 3289 |
| 3290 void FullCodeGenerator::EmitValueOf(CallRuntime* expr) { | 3290 void FullCodeGenerator::EmitValueOf(CallRuntime* expr) { |
| 3291 ZoneList<Expression*>* args = expr->arguments(); | 3291 ZoneList<Expression*>* args = expr->arguments(); |
| 3292 ASSERT(args->length() == 1); | 3292 DCHECK(args->length() == 1); |
| 3293 | 3293 |
| 3294 VisitForAccumulatorValue(args->at(0)); // Load the object. | 3294 VisitForAccumulatorValue(args->at(0)); // Load the object. |
| 3295 | 3295 |
| 3296 Label done; | 3296 Label done; |
| 3297 // If the object is a smi return the object. | 3297 // If the object is a smi return the object. |
| 3298 __ JumpIfSmi(eax, &done, Label::kNear); | 3298 __ JumpIfSmi(eax, &done, Label::kNear); |
| 3299 // If the object is not a value type, return the object. | 3299 // If the object is not a value type, return the object. |
| 3300 __ CmpObjectType(eax, JS_VALUE_TYPE, ebx); | 3300 __ CmpObjectType(eax, JS_VALUE_TYPE, ebx); |
| 3301 __ j(not_equal, &done, Label::kNear); | 3301 __ j(not_equal, &done, Label::kNear); |
| 3302 __ mov(eax, FieldOperand(eax, JSValue::kValueOffset)); | 3302 __ mov(eax, FieldOperand(eax, JSValue::kValueOffset)); |
| 3303 | 3303 |
| 3304 __ bind(&done); | 3304 __ bind(&done); |
| 3305 context()->Plug(eax); | 3305 context()->Plug(eax); |
| 3306 } | 3306 } |
| 3307 | 3307 |
| 3308 | 3308 |
| 3309 void FullCodeGenerator::EmitDateField(CallRuntime* expr) { | 3309 void FullCodeGenerator::EmitDateField(CallRuntime* expr) { |
| 3310 ZoneList<Expression*>* args = expr->arguments(); | 3310 ZoneList<Expression*>* args = expr->arguments(); |
| 3311 ASSERT(args->length() == 2); | 3311 DCHECK(args->length() == 2); |
| 3312 ASSERT_NE(NULL, args->at(1)->AsLiteral()); | 3312 DCHECK_NE(NULL, args->at(1)->AsLiteral()); |
| 3313 Smi* index = Smi::cast(*(args->at(1)->AsLiteral()->value())); | 3313 Smi* index = Smi::cast(*(args->at(1)->AsLiteral()->value())); |
| 3314 | 3314 |
| 3315 VisitForAccumulatorValue(args->at(0)); // Load the object. | 3315 VisitForAccumulatorValue(args->at(0)); // Load the object. |
| 3316 | 3316 |
| 3317 Label runtime, done, not_date_object; | 3317 Label runtime, done, not_date_object; |
| 3318 Register object = eax; | 3318 Register object = eax; |
| 3319 Register result = eax; | 3319 Register result = eax; |
| 3320 Register scratch = ecx; | 3320 Register scratch = ecx; |
| 3321 | 3321 |
| 3322 __ JumpIfSmi(object, ¬_date_object); | 3322 __ JumpIfSmi(object, ¬_date_object); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 3346 | 3346 |
| 3347 __ bind(¬_date_object); | 3347 __ bind(¬_date_object); |
| 3348 __ CallRuntime(Runtime::kThrowNotDateError, 0); | 3348 __ CallRuntime(Runtime::kThrowNotDateError, 0); |
| 3349 __ bind(&done); | 3349 __ bind(&done); |
| 3350 context()->Plug(result); | 3350 context()->Plug(result); |
| 3351 } | 3351 } |
| 3352 | 3352 |
| 3353 | 3353 |
| 3354 void FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) { | 3354 void FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) { |
| 3355 ZoneList<Expression*>* args = expr->arguments(); | 3355 ZoneList<Expression*>* args = expr->arguments(); |
| 3356 ASSERT_EQ(3, args->length()); | 3356 DCHECK_EQ(3, args->length()); |
| 3357 | 3357 |
| 3358 Register string = eax; | 3358 Register string = eax; |
| 3359 Register index = ebx; | 3359 Register index = ebx; |
| 3360 Register value = ecx; | 3360 Register value = ecx; |
| 3361 | 3361 |
| 3362 VisitForStackValue(args->at(1)); // index | 3362 VisitForStackValue(args->at(1)); // index |
| 3363 VisitForStackValue(args->at(2)); // value | 3363 VisitForStackValue(args->at(2)); // value |
| 3364 VisitForAccumulatorValue(args->at(0)); // string | 3364 VisitForAccumulatorValue(args->at(0)); // string |
| 3365 | 3365 |
| 3366 __ pop(value); | 3366 __ pop(value); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 3382 } | 3382 } |
| 3383 | 3383 |
| 3384 __ mov_b(FieldOperand(string, index, times_1, SeqOneByteString::kHeaderSize), | 3384 __ mov_b(FieldOperand(string, index, times_1, SeqOneByteString::kHeaderSize), |
| 3385 value); | 3385 value); |
| 3386 context()->Plug(string); | 3386 context()->Plug(string); |
| 3387 } | 3387 } |
| 3388 | 3388 |
| 3389 | 3389 |
| 3390 void FullCodeGenerator::EmitTwoByteSeqStringSetChar(CallRuntime* expr) { | 3390 void FullCodeGenerator::EmitTwoByteSeqStringSetChar(CallRuntime* expr) { |
| 3391 ZoneList<Expression*>* args = expr->arguments(); | 3391 ZoneList<Expression*>* args = expr->arguments(); |
| 3392 ASSERT_EQ(3, args->length()); | 3392 DCHECK_EQ(3, args->length()); |
| 3393 | 3393 |
| 3394 Register string = eax; | 3394 Register string = eax; |
| 3395 Register index = ebx; | 3395 Register index = ebx; |
| 3396 Register value = ecx; | 3396 Register value = ecx; |
| 3397 | 3397 |
| 3398 VisitForStackValue(args->at(1)); // index | 3398 VisitForStackValue(args->at(1)); // index |
| 3399 VisitForStackValue(args->at(2)); // value | 3399 VisitForStackValue(args->at(2)); // value |
| 3400 VisitForAccumulatorValue(args->at(0)); // string | 3400 VisitForAccumulatorValue(args->at(0)); // string |
| 3401 __ pop(value); | 3401 __ pop(value); |
| 3402 __ pop(index); | 3402 __ pop(index); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 3416 // No need to untag a smi for two-byte addressing. | 3416 // No need to untag a smi for two-byte addressing. |
| 3417 __ mov_w(FieldOperand(string, index, times_1, SeqTwoByteString::kHeaderSize), | 3417 __ mov_w(FieldOperand(string, index, times_1, SeqTwoByteString::kHeaderSize), |
| 3418 value); | 3418 value); |
| 3419 context()->Plug(string); | 3419 context()->Plug(string); |
| 3420 } | 3420 } |
| 3421 | 3421 |
| 3422 | 3422 |
| 3423 void FullCodeGenerator::EmitMathPow(CallRuntime* expr) { | 3423 void FullCodeGenerator::EmitMathPow(CallRuntime* expr) { |
| 3424 // Load the arguments on the stack and call the runtime function. | 3424 // Load the arguments on the stack and call the runtime function. |
| 3425 ZoneList<Expression*>* args = expr->arguments(); | 3425 ZoneList<Expression*>* args = expr->arguments(); |
| 3426 ASSERT(args->length() == 2); | 3426 DCHECK(args->length() == 2); |
| 3427 VisitForStackValue(args->at(0)); | 3427 VisitForStackValue(args->at(0)); |
| 3428 VisitForStackValue(args->at(1)); | 3428 VisitForStackValue(args->at(1)); |
| 3429 | 3429 |
| 3430 __ CallRuntime(Runtime::kMathPowSlow, 2); | 3430 __ CallRuntime(Runtime::kMathPowSlow, 2); |
| 3431 context()->Plug(eax); | 3431 context()->Plug(eax); |
| 3432 } | 3432 } |
| 3433 | 3433 |
| 3434 | 3434 |
| 3435 void FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) { | 3435 void FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) { |
| 3436 ZoneList<Expression*>* args = expr->arguments(); | 3436 ZoneList<Expression*>* args = expr->arguments(); |
| 3437 ASSERT(args->length() == 2); | 3437 DCHECK(args->length() == 2); |
| 3438 | 3438 |
| 3439 VisitForStackValue(args->at(0)); // Load the object. | 3439 VisitForStackValue(args->at(0)); // Load the object. |
| 3440 VisitForAccumulatorValue(args->at(1)); // Load the value. | 3440 VisitForAccumulatorValue(args->at(1)); // Load the value. |
| 3441 __ pop(ebx); // eax = value. ebx = object. | 3441 __ pop(ebx); // eax = value. ebx = object. |
| 3442 | 3442 |
| 3443 Label done; | 3443 Label done; |
| 3444 // If the object is a smi, return the value. | 3444 // If the object is a smi, return the value. |
| 3445 __ JumpIfSmi(ebx, &done, Label::kNear); | 3445 __ JumpIfSmi(ebx, &done, Label::kNear); |
| 3446 | 3446 |
| 3447 // If the object is not a value type, return the value. | 3447 // If the object is not a value type, return the value. |
| 3448 __ CmpObjectType(ebx, JS_VALUE_TYPE, ecx); | 3448 __ CmpObjectType(ebx, JS_VALUE_TYPE, ecx); |
| 3449 __ j(not_equal, &done, Label::kNear); | 3449 __ j(not_equal, &done, Label::kNear); |
| 3450 | 3450 |
| 3451 // Store the value. | 3451 // Store the value. |
| 3452 __ mov(FieldOperand(ebx, JSValue::kValueOffset), eax); | 3452 __ mov(FieldOperand(ebx, JSValue::kValueOffset), eax); |
| 3453 | 3453 |
| 3454 // Update the write barrier. Save the value as it will be | 3454 // Update the write barrier. Save the value as it will be |
| 3455 // overwritten by the write barrier code and is needed afterward. | 3455 // overwritten by the write barrier code and is needed afterward. |
| 3456 __ mov(edx, eax); | 3456 __ mov(edx, eax); |
| 3457 __ RecordWriteField(ebx, JSValue::kValueOffset, edx, ecx); | 3457 __ RecordWriteField(ebx, JSValue::kValueOffset, edx, ecx); |
| 3458 | 3458 |
| 3459 __ bind(&done); | 3459 __ bind(&done); |
| 3460 context()->Plug(eax); | 3460 context()->Plug(eax); |
| 3461 } | 3461 } |
| 3462 | 3462 |
| 3463 | 3463 |
| 3464 void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) { | 3464 void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) { |
| 3465 ZoneList<Expression*>* args = expr->arguments(); | 3465 ZoneList<Expression*>* args = expr->arguments(); |
| 3466 ASSERT_EQ(args->length(), 1); | 3466 DCHECK_EQ(args->length(), 1); |
| 3467 | 3467 |
| 3468 // Load the argument into eax and call the stub. | 3468 // Load the argument into eax and call the stub. |
| 3469 VisitForAccumulatorValue(args->at(0)); | 3469 VisitForAccumulatorValue(args->at(0)); |
| 3470 | 3470 |
| 3471 NumberToStringStub stub(isolate()); | 3471 NumberToStringStub stub(isolate()); |
| 3472 __ CallStub(&stub); | 3472 __ CallStub(&stub); |
| 3473 context()->Plug(eax); | 3473 context()->Plug(eax); |
| 3474 } | 3474 } |
| 3475 | 3475 |
| 3476 | 3476 |
| 3477 void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) { | 3477 void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) { |
| 3478 ZoneList<Expression*>* args = expr->arguments(); | 3478 ZoneList<Expression*>* args = expr->arguments(); |
| 3479 ASSERT(args->length() == 1); | 3479 DCHECK(args->length() == 1); |
| 3480 | 3480 |
| 3481 VisitForAccumulatorValue(args->at(0)); | 3481 VisitForAccumulatorValue(args->at(0)); |
| 3482 | 3482 |
| 3483 Label done; | 3483 Label done; |
| 3484 StringCharFromCodeGenerator generator(eax, ebx); | 3484 StringCharFromCodeGenerator generator(eax, ebx); |
| 3485 generator.GenerateFast(masm_); | 3485 generator.GenerateFast(masm_); |
| 3486 __ jmp(&done); | 3486 __ jmp(&done); |
| 3487 | 3487 |
| 3488 NopRuntimeCallHelper call_helper; | 3488 NopRuntimeCallHelper call_helper; |
| 3489 generator.GenerateSlow(masm_, call_helper); | 3489 generator.GenerateSlow(masm_, call_helper); |
| 3490 | 3490 |
| 3491 __ bind(&done); | 3491 __ bind(&done); |
| 3492 context()->Plug(ebx); | 3492 context()->Plug(ebx); |
| 3493 } | 3493 } |
| 3494 | 3494 |
| 3495 | 3495 |
| 3496 void FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) { | 3496 void FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) { |
| 3497 ZoneList<Expression*>* args = expr->arguments(); | 3497 ZoneList<Expression*>* args = expr->arguments(); |
| 3498 ASSERT(args->length() == 2); | 3498 DCHECK(args->length() == 2); |
| 3499 | 3499 |
| 3500 VisitForStackValue(args->at(0)); | 3500 VisitForStackValue(args->at(0)); |
| 3501 VisitForAccumulatorValue(args->at(1)); | 3501 VisitForAccumulatorValue(args->at(1)); |
| 3502 | 3502 |
| 3503 Register object = ebx; | 3503 Register object = ebx; |
| 3504 Register index = eax; | 3504 Register index = eax; |
| 3505 Register result = edx; | 3505 Register result = edx; |
| 3506 | 3506 |
| 3507 __ pop(object); | 3507 __ pop(object); |
| 3508 | 3508 |
| (...skipping 25 matching lines...) Expand all Loading... |
| 3534 NopRuntimeCallHelper call_helper; | 3534 NopRuntimeCallHelper call_helper; |
| 3535 generator.GenerateSlow(masm_, call_helper); | 3535 generator.GenerateSlow(masm_, call_helper); |
| 3536 | 3536 |
| 3537 __ bind(&done); | 3537 __ bind(&done); |
| 3538 context()->Plug(result); | 3538 context()->Plug(result); |
| 3539 } | 3539 } |
| 3540 | 3540 |
| 3541 | 3541 |
| 3542 void FullCodeGenerator::EmitStringCharAt(CallRuntime* expr) { | 3542 void FullCodeGenerator::EmitStringCharAt(CallRuntime* expr) { |
| 3543 ZoneList<Expression*>* args = expr->arguments(); | 3543 ZoneList<Expression*>* args = expr->arguments(); |
| 3544 ASSERT(args->length() == 2); | 3544 DCHECK(args->length() == 2); |
| 3545 | 3545 |
| 3546 VisitForStackValue(args->at(0)); | 3546 VisitForStackValue(args->at(0)); |
| 3547 VisitForAccumulatorValue(args->at(1)); | 3547 VisitForAccumulatorValue(args->at(1)); |
| 3548 | 3548 |
| 3549 Register object = ebx; | 3549 Register object = ebx; |
| 3550 Register index = eax; | 3550 Register index = eax; |
| 3551 Register scratch = edx; | 3551 Register scratch = edx; |
| 3552 Register result = eax; | 3552 Register result = eax; |
| 3553 | 3553 |
| 3554 __ pop(object); | 3554 __ pop(object); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 3582 NopRuntimeCallHelper call_helper; | 3582 NopRuntimeCallHelper call_helper; |
| 3583 generator.GenerateSlow(masm_, call_helper); | 3583 generator.GenerateSlow(masm_, call_helper); |
| 3584 | 3584 |
| 3585 __ bind(&done); | 3585 __ bind(&done); |
| 3586 context()->Plug(result); | 3586 context()->Plug(result); |
| 3587 } | 3587 } |
| 3588 | 3588 |
| 3589 | 3589 |
| 3590 void FullCodeGenerator::EmitStringAdd(CallRuntime* expr) { | 3590 void FullCodeGenerator::EmitStringAdd(CallRuntime* expr) { |
| 3591 ZoneList<Expression*>* args = expr->arguments(); | 3591 ZoneList<Expression*>* args = expr->arguments(); |
| 3592 ASSERT_EQ(2, args->length()); | 3592 DCHECK_EQ(2, args->length()); |
| 3593 VisitForStackValue(args->at(0)); | 3593 VisitForStackValue(args->at(0)); |
| 3594 VisitForAccumulatorValue(args->at(1)); | 3594 VisitForAccumulatorValue(args->at(1)); |
| 3595 | 3595 |
| 3596 __ pop(edx); | 3596 __ pop(edx); |
| 3597 StringAddStub stub(isolate(), STRING_ADD_CHECK_BOTH, NOT_TENURED); | 3597 StringAddStub stub(isolate(), STRING_ADD_CHECK_BOTH, NOT_TENURED); |
| 3598 __ CallStub(&stub); | 3598 __ CallStub(&stub); |
| 3599 context()->Plug(eax); | 3599 context()->Plug(eax); |
| 3600 } | 3600 } |
| 3601 | 3601 |
| 3602 | 3602 |
| 3603 void FullCodeGenerator::EmitStringCompare(CallRuntime* expr) { | 3603 void FullCodeGenerator::EmitStringCompare(CallRuntime* expr) { |
| 3604 ZoneList<Expression*>* args = expr->arguments(); | 3604 ZoneList<Expression*>* args = expr->arguments(); |
| 3605 ASSERT_EQ(2, args->length()); | 3605 DCHECK_EQ(2, args->length()); |
| 3606 | 3606 |
| 3607 VisitForStackValue(args->at(0)); | 3607 VisitForStackValue(args->at(0)); |
| 3608 VisitForStackValue(args->at(1)); | 3608 VisitForStackValue(args->at(1)); |
| 3609 | 3609 |
| 3610 StringCompareStub stub(isolate()); | 3610 StringCompareStub stub(isolate()); |
| 3611 __ CallStub(&stub); | 3611 __ CallStub(&stub); |
| 3612 context()->Plug(eax); | 3612 context()->Plug(eax); |
| 3613 } | 3613 } |
| 3614 | 3614 |
| 3615 | 3615 |
| 3616 void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) { | 3616 void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) { |
| 3617 ZoneList<Expression*>* args = expr->arguments(); | 3617 ZoneList<Expression*>* args = expr->arguments(); |
| 3618 ASSERT(args->length() >= 2); | 3618 DCHECK(args->length() >= 2); |
| 3619 | 3619 |
| 3620 int arg_count = args->length() - 2; // 2 ~ receiver and function. | 3620 int arg_count = args->length() - 2; // 2 ~ receiver and function. |
| 3621 for (int i = 0; i < arg_count + 1; ++i) { | 3621 for (int i = 0; i < arg_count + 1; ++i) { |
| 3622 VisitForStackValue(args->at(i)); | 3622 VisitForStackValue(args->at(i)); |
| 3623 } | 3623 } |
| 3624 VisitForAccumulatorValue(args->last()); // Function. | 3624 VisitForAccumulatorValue(args->last()); // Function. |
| 3625 | 3625 |
| 3626 Label runtime, done; | 3626 Label runtime, done; |
| 3627 // Check for non-function argument (including proxy). | 3627 // Check for non-function argument (including proxy). |
| 3628 __ JumpIfSmi(eax, &runtime); | 3628 __ JumpIfSmi(eax, &runtime); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 3642 __ bind(&done); | 3642 __ bind(&done); |
| 3643 | 3643 |
| 3644 context()->Plug(eax); | 3644 context()->Plug(eax); |
| 3645 } | 3645 } |
| 3646 | 3646 |
| 3647 | 3647 |
| 3648 void FullCodeGenerator::EmitRegExpConstructResult(CallRuntime* expr) { | 3648 void FullCodeGenerator::EmitRegExpConstructResult(CallRuntime* expr) { |
| 3649 // Load the arguments on the stack and call the stub. | 3649 // Load the arguments on the stack and call the stub. |
| 3650 RegExpConstructResultStub stub(isolate()); | 3650 RegExpConstructResultStub stub(isolate()); |
| 3651 ZoneList<Expression*>* args = expr->arguments(); | 3651 ZoneList<Expression*>* args = expr->arguments(); |
| 3652 ASSERT(args->length() == 3); | 3652 DCHECK(args->length() == 3); |
| 3653 VisitForStackValue(args->at(0)); | 3653 VisitForStackValue(args->at(0)); |
| 3654 VisitForStackValue(args->at(1)); | 3654 VisitForStackValue(args->at(1)); |
| 3655 VisitForAccumulatorValue(args->at(2)); | 3655 VisitForAccumulatorValue(args->at(2)); |
| 3656 __ pop(ebx); | 3656 __ pop(ebx); |
| 3657 __ pop(ecx); | 3657 __ pop(ecx); |
| 3658 __ CallStub(&stub); | 3658 __ CallStub(&stub); |
| 3659 context()->Plug(eax); | 3659 context()->Plug(eax); |
| 3660 } | 3660 } |
| 3661 | 3661 |
| 3662 | 3662 |
| 3663 void FullCodeGenerator::EmitGetFromCache(CallRuntime* expr) { | 3663 void FullCodeGenerator::EmitGetFromCache(CallRuntime* expr) { |
| 3664 ZoneList<Expression*>* args = expr->arguments(); | 3664 ZoneList<Expression*>* args = expr->arguments(); |
| 3665 ASSERT_EQ(2, args->length()); | 3665 DCHECK_EQ(2, args->length()); |
| 3666 | 3666 |
| 3667 ASSERT_NE(NULL, args->at(0)->AsLiteral()); | 3667 DCHECK_NE(NULL, args->at(0)->AsLiteral()); |
| 3668 int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->value()))->value(); | 3668 int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->value()))->value(); |
| 3669 | 3669 |
| 3670 Handle<FixedArray> jsfunction_result_caches( | 3670 Handle<FixedArray> jsfunction_result_caches( |
| 3671 isolate()->native_context()->jsfunction_result_caches()); | 3671 isolate()->native_context()->jsfunction_result_caches()); |
| 3672 if (jsfunction_result_caches->length() <= cache_id) { | 3672 if (jsfunction_result_caches->length() <= cache_id) { |
| 3673 __ Abort(kAttemptToUseUndefinedCache); | 3673 __ Abort(kAttemptToUseUndefinedCache); |
| 3674 __ mov(eax, isolate()->factory()->undefined_value()); | 3674 __ mov(eax, isolate()->factory()->undefined_value()); |
| 3675 context()->Plug(eax); | 3675 context()->Plug(eax); |
| 3676 return; | 3676 return; |
| 3677 } | 3677 } |
| (...skipping 26 matching lines...) Expand all Loading... |
| 3704 __ push(key); | 3704 __ push(key); |
| 3705 __ CallRuntime(Runtime::kGetFromCache, 2); | 3705 __ CallRuntime(Runtime::kGetFromCache, 2); |
| 3706 | 3706 |
| 3707 __ bind(&done); | 3707 __ bind(&done); |
| 3708 context()->Plug(eax); | 3708 context()->Plug(eax); |
| 3709 } | 3709 } |
| 3710 | 3710 |
| 3711 | 3711 |
| 3712 void FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) { | 3712 void FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) { |
| 3713 ZoneList<Expression*>* args = expr->arguments(); | 3713 ZoneList<Expression*>* args = expr->arguments(); |
| 3714 ASSERT(args->length() == 1); | 3714 DCHECK(args->length() == 1); |
| 3715 | 3715 |
| 3716 VisitForAccumulatorValue(args->at(0)); | 3716 VisitForAccumulatorValue(args->at(0)); |
| 3717 | 3717 |
| 3718 __ AssertString(eax); | 3718 __ AssertString(eax); |
| 3719 | 3719 |
| 3720 Label materialize_true, materialize_false; | 3720 Label materialize_true, materialize_false; |
| 3721 Label* if_true = NULL; | 3721 Label* if_true = NULL; |
| 3722 Label* if_false = NULL; | 3722 Label* if_false = NULL; |
| 3723 Label* fall_through = NULL; | 3723 Label* fall_through = NULL; |
| 3724 context()->PrepareTest(&materialize_true, &materialize_false, | 3724 context()->PrepareTest(&materialize_true, &materialize_false, |
| 3725 &if_true, &if_false, &fall_through); | 3725 &if_true, &if_false, &fall_through); |
| 3726 | 3726 |
| 3727 __ test(FieldOperand(eax, String::kHashFieldOffset), | 3727 __ test(FieldOperand(eax, String::kHashFieldOffset), |
| 3728 Immediate(String::kContainsCachedArrayIndexMask)); | 3728 Immediate(String::kContainsCachedArrayIndexMask)); |
| 3729 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 3729 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
| 3730 Split(zero, if_true, if_false, fall_through); | 3730 Split(zero, if_true, if_false, fall_through); |
| 3731 | 3731 |
| 3732 context()->Plug(if_true, if_false); | 3732 context()->Plug(if_true, if_false); |
| 3733 } | 3733 } |
| 3734 | 3734 |
| 3735 | 3735 |
| 3736 void FullCodeGenerator::EmitGetCachedArrayIndex(CallRuntime* expr) { | 3736 void FullCodeGenerator::EmitGetCachedArrayIndex(CallRuntime* expr) { |
| 3737 ZoneList<Expression*>* args = expr->arguments(); | 3737 ZoneList<Expression*>* args = expr->arguments(); |
| 3738 ASSERT(args->length() == 1); | 3738 DCHECK(args->length() == 1); |
| 3739 VisitForAccumulatorValue(args->at(0)); | 3739 VisitForAccumulatorValue(args->at(0)); |
| 3740 | 3740 |
| 3741 __ AssertString(eax); | 3741 __ AssertString(eax); |
| 3742 | 3742 |
| 3743 __ mov(eax, FieldOperand(eax, String::kHashFieldOffset)); | 3743 __ mov(eax, FieldOperand(eax, String::kHashFieldOffset)); |
| 3744 __ IndexFromHash(eax, eax); | 3744 __ IndexFromHash(eax, eax); |
| 3745 | 3745 |
| 3746 context()->Plug(eax); | 3746 context()->Plug(eax); |
| 3747 } | 3747 } |
| 3748 | 3748 |
| 3749 | 3749 |
| 3750 void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) { | 3750 void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) { |
| 3751 Label bailout, done, one_char_separator, long_separator, | 3751 Label bailout, done, one_char_separator, long_separator, |
| 3752 non_trivial_array, not_size_one_array, loop, | 3752 non_trivial_array, not_size_one_array, loop, |
| 3753 loop_1, loop_1_condition, loop_2, loop_2_entry, loop_3, loop_3_entry; | 3753 loop_1, loop_1_condition, loop_2, loop_2_entry, loop_3, loop_3_entry; |
| 3754 | 3754 |
| 3755 ZoneList<Expression*>* args = expr->arguments(); | 3755 ZoneList<Expression*>* args = expr->arguments(); |
| 3756 ASSERT(args->length() == 2); | 3756 DCHECK(args->length() == 2); |
| 3757 // We will leave the separator on the stack until the end of the function. | 3757 // We will leave the separator on the stack until the end of the function. |
| 3758 VisitForStackValue(args->at(1)); | 3758 VisitForStackValue(args->at(1)); |
| 3759 // Load this to eax (= array) | 3759 // Load this to eax (= array) |
| 3760 VisitForAccumulatorValue(args->at(0)); | 3760 VisitForAccumulatorValue(args->at(0)); |
| 3761 // All aliases of the same register have disjoint lifetimes. | 3761 // All aliases of the same register have disjoint lifetimes. |
| 3762 Register array = eax; | 3762 Register array = eax; |
| 3763 Register elements = no_reg; // Will be eax. | 3763 Register elements = no_reg; // Will be eax. |
| 3764 | 3764 |
| 3765 Register index = edx; | 3765 Register index = edx; |
| 3766 | 3766 |
| (...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4005 __ mov(eax, result_operand); | 4005 __ mov(eax, result_operand); |
| 4006 // Drop temp values from the stack, and restore context register. | 4006 // Drop temp values from the stack, and restore context register. |
| 4007 __ add(esp, Immediate(3 * kPointerSize)); | 4007 __ add(esp, Immediate(3 * kPointerSize)); |
| 4008 | 4008 |
| 4009 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 4009 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 4010 context()->Plug(eax); | 4010 context()->Plug(eax); |
| 4011 } | 4011 } |
| 4012 | 4012 |
| 4013 | 4013 |
| 4014 void FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) { | 4014 void FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) { |
| 4015 ASSERT(expr->arguments()->length() == 0); | 4015 DCHECK(expr->arguments()->length() == 0); |
| 4016 ExternalReference debug_is_active = | 4016 ExternalReference debug_is_active = |
| 4017 ExternalReference::debug_is_active_address(isolate()); | 4017 ExternalReference::debug_is_active_address(isolate()); |
| 4018 __ movzx_b(eax, Operand::StaticVariable(debug_is_active)); | 4018 __ movzx_b(eax, Operand::StaticVariable(debug_is_active)); |
| 4019 __ SmiTag(eax); | 4019 __ SmiTag(eax); |
| 4020 context()->Plug(eax); | 4020 context()->Plug(eax); |
| 4021 } | 4021 } |
| 4022 | 4022 |
| 4023 | 4023 |
| 4024 void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { | 4024 void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { |
| 4025 if (expr->function() != NULL && | 4025 if (expr->function() != NULL && |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4093 if (property != NULL) { | 4093 if (property != NULL) { |
| 4094 VisitForStackValue(property->obj()); | 4094 VisitForStackValue(property->obj()); |
| 4095 VisitForStackValue(property->key()); | 4095 VisitForStackValue(property->key()); |
| 4096 __ push(Immediate(Smi::FromInt(strict_mode()))); | 4096 __ push(Immediate(Smi::FromInt(strict_mode()))); |
| 4097 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); | 4097 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); |
| 4098 context()->Plug(eax); | 4098 context()->Plug(eax); |
| 4099 } else if (proxy != NULL) { | 4099 } else if (proxy != NULL) { |
| 4100 Variable* var = proxy->var(); | 4100 Variable* var = proxy->var(); |
| 4101 // Delete of an unqualified identifier is disallowed in strict mode | 4101 // Delete of an unqualified identifier is disallowed in strict mode |
| 4102 // but "delete this" is allowed. | 4102 // but "delete this" is allowed. |
| 4103 ASSERT(strict_mode() == SLOPPY || var->is_this()); | 4103 DCHECK(strict_mode() == SLOPPY || var->is_this()); |
| 4104 if (var->IsUnallocated()) { | 4104 if (var->IsUnallocated()) { |
| 4105 __ push(GlobalObjectOperand()); | 4105 __ push(GlobalObjectOperand()); |
| 4106 __ push(Immediate(var->name())); | 4106 __ push(Immediate(var->name())); |
| 4107 __ push(Immediate(Smi::FromInt(SLOPPY))); | 4107 __ push(Immediate(Smi::FromInt(SLOPPY))); |
| 4108 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); | 4108 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); |
| 4109 context()->Plug(eax); | 4109 context()->Plug(eax); |
| 4110 } else if (var->IsStackAllocated() || var->IsContextSlot()) { | 4110 } else if (var->IsStackAllocated() || var->IsContextSlot()) { |
| 4111 // Result of deleting non-global variables is false. 'this' is | 4111 // Result of deleting non-global variables is false. 'this' is |
| 4112 // not really a variable, though we implement it as one. The | 4112 // not really a variable, though we implement it as one. The |
| 4113 // subexpression does not have side effects. | 4113 // subexpression does not have side effects. |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4148 VisitForControl(expr->expression(), | 4148 VisitForControl(expr->expression(), |
| 4149 test->false_label(), | 4149 test->false_label(), |
| 4150 test->true_label(), | 4150 test->true_label(), |
| 4151 test->fall_through()); | 4151 test->fall_through()); |
| 4152 context()->Plug(test->true_label(), test->false_label()); | 4152 context()->Plug(test->true_label(), test->false_label()); |
| 4153 } else { | 4153 } else { |
| 4154 // We handle value contexts explicitly rather than simply visiting | 4154 // We handle value contexts explicitly rather than simply visiting |
| 4155 // for control and plugging the control flow into the context, | 4155 // for control and plugging the control flow into the context, |
| 4156 // because we need to prepare a pair of extra administrative AST ids | 4156 // because we need to prepare a pair of extra administrative AST ids |
| 4157 // for the optimizing compiler. | 4157 // for the optimizing compiler. |
| 4158 ASSERT(context()->IsAccumulatorValue() || context()->IsStackValue()); | 4158 DCHECK(context()->IsAccumulatorValue() || context()->IsStackValue()); |
| 4159 Label materialize_true, materialize_false, done; | 4159 Label materialize_true, materialize_false, done; |
| 4160 VisitForControl(expr->expression(), | 4160 VisitForControl(expr->expression(), |
| 4161 &materialize_false, | 4161 &materialize_false, |
| 4162 &materialize_true, | 4162 &materialize_true, |
| 4163 &materialize_true); | 4163 &materialize_true); |
| 4164 __ bind(&materialize_true); | 4164 __ bind(&materialize_true); |
| 4165 PrepareForBailoutForId(expr->MaterializeTrueId(), NO_REGISTERS); | 4165 PrepareForBailoutForId(expr->MaterializeTrueId(), NO_REGISTERS); |
| 4166 if (context()->IsAccumulatorValue()) { | 4166 if (context()->IsAccumulatorValue()) { |
| 4167 __ mov(eax, isolate()->factory()->true_value()); | 4167 __ mov(eax, isolate()->factory()->true_value()); |
| 4168 } else { | 4168 } else { |
| (...skipping 22 matching lines...) Expand all Loading... |
| 4191 break; | 4191 break; |
| 4192 } | 4192 } |
| 4193 | 4193 |
| 4194 default: | 4194 default: |
| 4195 UNREACHABLE(); | 4195 UNREACHABLE(); |
| 4196 } | 4196 } |
| 4197 } | 4197 } |
| 4198 | 4198 |
| 4199 | 4199 |
| 4200 void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { | 4200 void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { |
| 4201 ASSERT(expr->expression()->IsValidReferenceExpression()); | 4201 DCHECK(expr->expression()->IsValidReferenceExpression()); |
| 4202 | 4202 |
| 4203 Comment cmnt(masm_, "[ CountOperation"); | 4203 Comment cmnt(masm_, "[ CountOperation"); |
| 4204 SetSourcePosition(expr->position()); | 4204 SetSourcePosition(expr->position()); |
| 4205 | 4205 |
| 4206 // Expression can only be a property, a global or a (parameter or local) | 4206 // Expression can only be a property, a global or a (parameter or local) |
| 4207 // slot. | 4207 // slot. |
| 4208 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; | 4208 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; |
| 4209 LhsKind assign_type = VARIABLE; | 4209 LhsKind assign_type = VARIABLE; |
| 4210 Property* prop = expr->expression()->AsProperty(); | 4210 Property* prop = expr->expression()->AsProperty(); |
| 4211 // In case of a property we use the uninitialized expression context | 4211 // In case of a property we use the uninitialized expression context |
| 4212 // of the key to detect a named property. | 4212 // of the key to detect a named property. |
| 4213 if (prop != NULL) { | 4213 if (prop != NULL) { |
| 4214 assign_type = | 4214 assign_type = |
| 4215 (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY; | 4215 (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY; |
| 4216 } | 4216 } |
| 4217 | 4217 |
| 4218 // Evaluate expression and get value. | 4218 // Evaluate expression and get value. |
| 4219 if (assign_type == VARIABLE) { | 4219 if (assign_type == VARIABLE) { |
| 4220 ASSERT(expr->expression()->AsVariableProxy()->var() != NULL); | 4220 DCHECK(expr->expression()->AsVariableProxy()->var() != NULL); |
| 4221 AccumulatorValueContext context(this); | 4221 AccumulatorValueContext context(this); |
| 4222 EmitVariableLoad(expr->expression()->AsVariableProxy()); | 4222 EmitVariableLoad(expr->expression()->AsVariableProxy()); |
| 4223 } else { | 4223 } else { |
| 4224 // Reserve space for result of postfix operation. | 4224 // Reserve space for result of postfix operation. |
| 4225 if (expr->is_postfix() && !context()->IsEffect()) { | 4225 if (expr->is_postfix() && !context()->IsEffect()) { |
| 4226 __ push(Immediate(Smi::FromInt(0))); | 4226 __ push(Immediate(Smi::FromInt(0))); |
| 4227 } | 4227 } |
| 4228 if (assign_type == NAMED_PROPERTY) { | 4228 if (assign_type == NAMED_PROPERTY) { |
| 4229 // Put the object both on the stack and in the register. | 4229 // Put the object both on the stack and in the register. |
| 4230 VisitForStackValue(prop->obj()); | 4230 VisitForStackValue(prop->obj()); |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4380 context()->Plug(eax); | 4380 context()->Plug(eax); |
| 4381 } | 4381 } |
| 4382 break; | 4382 break; |
| 4383 } | 4383 } |
| 4384 } | 4384 } |
| 4385 } | 4385 } |
| 4386 | 4386 |
| 4387 | 4387 |
| 4388 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { | 4388 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { |
| 4389 VariableProxy* proxy = expr->AsVariableProxy(); | 4389 VariableProxy* proxy = expr->AsVariableProxy(); |
| 4390 ASSERT(!context()->IsEffect()); | 4390 DCHECK(!context()->IsEffect()); |
| 4391 ASSERT(!context()->IsTest()); | 4391 DCHECK(!context()->IsTest()); |
| 4392 | 4392 |
| 4393 if (proxy != NULL && proxy->var()->IsUnallocated()) { | 4393 if (proxy != NULL && proxy->var()->IsUnallocated()) { |
| 4394 Comment cmnt(masm_, "[ Global variable"); | 4394 Comment cmnt(masm_, "[ Global variable"); |
| 4395 __ mov(LoadIC::ReceiverRegister(), GlobalObjectOperand()); | 4395 __ mov(LoadIC::ReceiverRegister(), GlobalObjectOperand()); |
| 4396 __ mov(LoadIC::NameRegister(), Immediate(proxy->name())); | 4396 __ mov(LoadIC::NameRegister(), Immediate(proxy->name())); |
| 4397 if (FLAG_vector_ics) { | 4397 if (FLAG_vector_ics) { |
| 4398 __ mov(LoadIC::SlotRegister(), | 4398 __ mov(LoadIC::SlotRegister(), |
| 4399 Immediate(Smi::FromInt(proxy->VariableFeedbackSlot()))); | 4399 Immediate(Smi::FromInt(proxy->VariableFeedbackSlot()))); |
| 4400 } | 4400 } |
| 4401 // Use a regular load, not a contextual load, to avoid a reference | 4401 // Use a regular load, not a contextual load, to avoid a reference |
| (...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4612 return eax; | 4612 return eax; |
| 4613 } | 4613 } |
| 4614 | 4614 |
| 4615 | 4615 |
| 4616 Register FullCodeGenerator::context_register() { | 4616 Register FullCodeGenerator::context_register() { |
| 4617 return esi; | 4617 return esi; |
| 4618 } | 4618 } |
| 4619 | 4619 |
| 4620 | 4620 |
| 4621 void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { | 4621 void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { |
| 4622 ASSERT_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset); | 4622 DCHECK_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset); |
| 4623 __ mov(Operand(ebp, frame_offset), value); | 4623 __ mov(Operand(ebp, frame_offset), value); |
| 4624 } | 4624 } |
| 4625 | 4625 |
| 4626 | 4626 |
| 4627 void FullCodeGenerator::LoadContextField(Register dst, int context_index) { | 4627 void FullCodeGenerator::LoadContextField(Register dst, int context_index) { |
| 4628 __ mov(dst, ContextOperand(esi, context_index)); | 4628 __ mov(dst, ContextOperand(esi, context_index)); |
| 4629 } | 4629 } |
| 4630 | 4630 |
| 4631 | 4631 |
| 4632 void FullCodeGenerator::PushFunctionArgumentForContextAllocation() { | 4632 void FullCodeGenerator::PushFunctionArgumentForContextAllocation() { |
| 4633 Scope* declaration_scope = scope()->DeclarationScope(); | 4633 Scope* declaration_scope = scope()->DeclarationScope(); |
| 4634 if (declaration_scope->is_global_scope() || | 4634 if (declaration_scope->is_global_scope() || |
| 4635 declaration_scope->is_module_scope()) { | 4635 declaration_scope->is_module_scope()) { |
| 4636 // Contexts nested in the native context have a canonical empty function | 4636 // Contexts nested in the native context have a canonical empty function |
| 4637 // as their closure, not the anonymous closure containing the global | 4637 // as their closure, not the anonymous closure containing the global |
| 4638 // code. Pass a smi sentinel and let the runtime look up the empty | 4638 // code. Pass a smi sentinel and let the runtime look up the empty |
| 4639 // function. | 4639 // function. |
| 4640 __ push(Immediate(Smi::FromInt(0))); | 4640 __ push(Immediate(Smi::FromInt(0))); |
| 4641 } else if (declaration_scope->is_eval_scope()) { | 4641 } else if (declaration_scope->is_eval_scope()) { |
| 4642 // Contexts nested inside eval code have the same closure as the context | 4642 // Contexts nested inside eval code have the same closure as the context |
| 4643 // calling eval, not the anonymous closure containing the eval code. | 4643 // calling eval, not the anonymous closure containing the eval code. |
| 4644 // Fetch it from the context. | 4644 // Fetch it from the context. |
| 4645 __ push(ContextOperand(esi, Context::CLOSURE_INDEX)); | 4645 __ push(ContextOperand(esi, Context::CLOSURE_INDEX)); |
| 4646 } else { | 4646 } else { |
| 4647 ASSERT(declaration_scope->is_function_scope()); | 4647 DCHECK(declaration_scope->is_function_scope()); |
| 4648 __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); | 4648 __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
| 4649 } | 4649 } |
| 4650 } | 4650 } |
| 4651 | 4651 |
| 4652 | 4652 |
| 4653 // ---------------------------------------------------------------------------- | 4653 // ---------------------------------------------------------------------------- |
| 4654 // Non-local control flow support. | 4654 // Non-local control flow support. |
| 4655 | 4655 |
| 4656 void FullCodeGenerator::EnterFinallyBlock() { | 4656 void FullCodeGenerator::EnterFinallyBlock() { |
| 4657 // Cook return address on top of stack (smi encoded Code* delta) | 4657 // Cook return address on top of stack (smi encoded Code* delta) |
| 4658 ASSERT(!result_register().is(edx)); | 4658 DCHECK(!result_register().is(edx)); |
| 4659 __ pop(edx); | 4659 __ pop(edx); |
| 4660 __ sub(edx, Immediate(masm_->CodeObject())); | 4660 __ sub(edx, Immediate(masm_->CodeObject())); |
| 4661 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1); | 4661 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1); |
| 4662 STATIC_ASSERT(kSmiTag == 0); | 4662 STATIC_ASSERT(kSmiTag == 0); |
| 4663 __ SmiTag(edx); | 4663 __ SmiTag(edx); |
| 4664 __ push(edx); | 4664 __ push(edx); |
| 4665 | 4665 |
| 4666 // Store result register while executing finally block. | 4666 // Store result register while executing finally block. |
| 4667 __ push(result_register()); | 4667 __ push(result_register()); |
| 4668 | 4668 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 4679 __ push(edx); | 4679 __ push(edx); |
| 4680 | 4680 |
| 4681 ExternalReference pending_message_script = | 4681 ExternalReference pending_message_script = |
| 4682 ExternalReference::address_of_pending_message_script(isolate()); | 4682 ExternalReference::address_of_pending_message_script(isolate()); |
| 4683 __ mov(edx, Operand::StaticVariable(pending_message_script)); | 4683 __ mov(edx, Operand::StaticVariable(pending_message_script)); |
| 4684 __ push(edx); | 4684 __ push(edx); |
| 4685 } | 4685 } |
| 4686 | 4686 |
| 4687 | 4687 |
| 4688 void FullCodeGenerator::ExitFinallyBlock() { | 4688 void FullCodeGenerator::ExitFinallyBlock() { |
| 4689 ASSERT(!result_register().is(edx)); | 4689 DCHECK(!result_register().is(edx)); |
| 4690 // Restore pending message from stack. | 4690 // Restore pending message from stack. |
| 4691 __ pop(edx); | 4691 __ pop(edx); |
| 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 __ mov(Operand::StaticVariable(pending_message_script), edx); | 4694 __ mov(Operand::StaticVariable(pending_message_script), edx); |
| 4695 | 4695 |
| 4696 __ pop(edx); | 4696 __ pop(edx); |
| 4697 __ SmiUntag(edx); | 4697 __ SmiUntag(edx); |
| 4698 ExternalReference has_pending_message = | 4698 ExternalReference has_pending_message = |
| 4699 ExternalReference::address_of_has_pending_message(isolate()); | 4699 ExternalReference::address_of_has_pending_message(isolate()); |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4790 unoptimized_code, call_target_address, replacement_code); | 4790 unoptimized_code, call_target_address, replacement_code); |
| 4791 } | 4791 } |
| 4792 | 4792 |
| 4793 | 4793 |
| 4794 BackEdgeTable::BackEdgeState BackEdgeTable::GetBackEdgeState( | 4794 BackEdgeTable::BackEdgeState BackEdgeTable::GetBackEdgeState( |
| 4795 Isolate* isolate, | 4795 Isolate* isolate, |
| 4796 Code* unoptimized_code, | 4796 Code* unoptimized_code, |
| 4797 Address pc) { | 4797 Address pc) { |
| 4798 Address call_target_address = pc - kIntSize; | 4798 Address call_target_address = pc - kIntSize; |
| 4799 Address jns_instr_address = call_target_address - 3; | 4799 Address jns_instr_address = call_target_address - 3; |
| 4800 ASSERT_EQ(kCallInstruction, *(call_target_address - 1)); | 4800 DCHECK_EQ(kCallInstruction, *(call_target_address - 1)); |
| 4801 | 4801 |
| 4802 if (*jns_instr_address == kJnsInstruction) { | 4802 if (*jns_instr_address == kJnsInstruction) { |
| 4803 ASSERT_EQ(kJnsOffset, *(call_target_address - 2)); | 4803 DCHECK_EQ(kJnsOffset, *(call_target_address - 2)); |
| 4804 ASSERT_EQ(isolate->builtins()->InterruptCheck()->entry(), | 4804 DCHECK_EQ(isolate->builtins()->InterruptCheck()->entry(), |
| 4805 Assembler::target_address_at(call_target_address, | 4805 Assembler::target_address_at(call_target_address, |
| 4806 unoptimized_code)); | 4806 unoptimized_code)); |
| 4807 return INTERRUPT; | 4807 return INTERRUPT; |
| 4808 } | 4808 } |
| 4809 | 4809 |
| 4810 ASSERT_EQ(kNopByteOne, *jns_instr_address); | 4810 DCHECK_EQ(kNopByteOne, *jns_instr_address); |
| 4811 ASSERT_EQ(kNopByteTwo, *(call_target_address - 2)); | 4811 DCHECK_EQ(kNopByteTwo, *(call_target_address - 2)); |
| 4812 | 4812 |
| 4813 if (Assembler::target_address_at(call_target_address, unoptimized_code) == | 4813 if (Assembler::target_address_at(call_target_address, unoptimized_code) == |
| 4814 isolate->builtins()->OnStackReplacement()->entry()) { | 4814 isolate->builtins()->OnStackReplacement()->entry()) { |
| 4815 return ON_STACK_REPLACEMENT; | 4815 return ON_STACK_REPLACEMENT; |
| 4816 } | 4816 } |
| 4817 | 4817 |
| 4818 ASSERT_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(), | 4818 DCHECK_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(), |
| 4819 Assembler::target_address_at(call_target_address, | 4819 Assembler::target_address_at(call_target_address, |
| 4820 unoptimized_code)); | 4820 unoptimized_code)); |
| 4821 return OSR_AFTER_STACK_CHECK; | 4821 return OSR_AFTER_STACK_CHECK; |
| 4822 } | 4822 } |
| 4823 | 4823 |
| 4824 | 4824 |
| 4825 } } // namespace v8::internal | 4825 } } // namespace v8::internal |
| 4826 | 4826 |
| 4827 #endif // V8_TARGET_ARCH_X87 | 4827 #endif // V8_TARGET_ARCH_X87 |
| OLD | NEW |