| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 159 if (locals_count == 1) { | 159 if (locals_count == 1) { |
| 160 __ push(Immediate(isolate()->factory()->undefined_value())); | 160 __ push(Immediate(isolate()->factory()->undefined_value())); |
| 161 } else if (locals_count > 1) { | 161 } else if (locals_count > 1) { |
| 162 __ mov(eax, Immediate(isolate()->factory()->undefined_value())); | 162 __ mov(eax, Immediate(isolate()->factory()->undefined_value())); |
| 163 for (int i = 0; i < locals_count; i++) { | 163 for (int i = 0; i < locals_count; i++) { |
| 164 __ push(eax); | 164 __ push(eax); |
| 165 } | 165 } |
| 166 } | 166 } |
| 167 } | 167 } |
| 168 | 168 |
| 169 set_stack_height(2 + scope()->num_stack_slots()); |
| 170 if (FLAG_verify_stack_height) { |
| 171 verify_stack_height(); |
| 172 } |
| 173 |
| 169 bool function_in_register = true; | 174 bool function_in_register = true; |
| 170 | 175 |
| 171 // Possibly allocate a local context. | 176 // Possibly allocate a local context. |
| 172 int heap_slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; | 177 int heap_slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; |
| 173 if (heap_slots > 0) { | 178 if (heap_slots > 0) { |
| 174 Comment cmnt(masm_, "[ Allocate local context"); | 179 Comment cmnt(masm_, "[ Allocate local context"); |
| 175 // Argument to NewContext is the function, which is still in edi. | 180 // Argument to NewContext is the function, which is still in edi. |
| 176 __ push(edi); | 181 __ push(edi); |
| 177 if (heap_slots <= FastNewContextStub::kMaximumSlots) { | 182 if (heap_slots <= FastNewContextStub::kMaximumSlots) { |
| 178 FastNewContextStub stub(heap_slots); | 183 FastNewContextStub stub(heap_slots); |
| (...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 352 #ifdef ENABLE_DEBUGGER_SUPPORT | 357 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 353 // Check that the size of the code used for returning is large enough | 358 // Check that the size of the code used for returning is large enough |
| 354 // for the debugger's requirements. | 359 // for the debugger's requirements. |
| 355 ASSERT(Assembler::kJSReturnSequenceLength <= | 360 ASSERT(Assembler::kJSReturnSequenceLength <= |
| 356 masm_->SizeOfCodeGeneratedSince(&check_exit_codesize)); | 361 masm_->SizeOfCodeGeneratedSince(&check_exit_codesize)); |
| 357 #endif | 362 #endif |
| 358 } | 363 } |
| 359 } | 364 } |
| 360 | 365 |
| 361 | 366 |
| 367 void FullCodeGenerator::verify_stack_height() { |
| 368 ASSERT(FLAG_verify_stack_height); |
| 369 __ sub(Operand(ebp), Immediate(kPointerSize * stack_height())); |
| 370 __ cmp(ebp, Operand(esp)); |
| 371 __ Assert(equal, "Full codegen stack height not as expected."); |
| 372 __ add(Operand(ebp), Immediate(kPointerSize * stack_height())); |
| 373 } |
| 374 |
| 375 |
| 362 void FullCodeGenerator::EffectContext::Plug(Slot* slot) const { | 376 void FullCodeGenerator::EffectContext::Plug(Slot* slot) const { |
| 363 } | 377 } |
| 364 | 378 |
| 365 | 379 |
| 366 void FullCodeGenerator::AccumulatorValueContext::Plug(Slot* slot) const { | 380 void FullCodeGenerator::AccumulatorValueContext::Plug(Slot* slot) const { |
| 367 MemOperand slot_operand = codegen()->EmitSlotSearch(slot, result_register()); | 381 MemOperand slot_operand = codegen()->EmitSlotSearch(slot, result_register()); |
| 368 __ mov(result_register(), slot_operand); | 382 __ mov(result_register(), slot_operand); |
| 369 } | 383 } |
| 370 | 384 |
| 371 | 385 |
| 372 void FullCodeGenerator::StackValueContext::Plug(Slot* slot) const { | 386 void FullCodeGenerator::StackValueContext::Plug(Slot* slot) const { |
| 373 MemOperand slot_operand = codegen()->EmitSlotSearch(slot, result_register()); | 387 MemOperand slot_operand = codegen()->EmitSlotSearch(slot, result_register()); |
| 374 // Memory operands can be pushed directly. | 388 // Memory operands can be pushed directly. |
| 375 __ push(slot_operand); | 389 __ push(slot_operand); |
| 390 codegen()->increment_stack_height(); |
| 376 } | 391 } |
| 377 | 392 |
| 378 | 393 |
| 379 void FullCodeGenerator::TestContext::Plug(Slot* slot) const { | 394 void FullCodeGenerator::TestContext::Plug(Slot* slot) const { |
| 380 // For simplicity we always test the accumulator register. | 395 // For simplicity we always test the accumulator register. |
| 381 codegen()->Move(result_register(), slot); | 396 codegen()->Move(result_register(), slot); |
| 382 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); | 397 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); |
| 383 codegen()->DoTest(this); | 398 codegen()->DoTest(this); |
| 384 } | 399 } |
| 385 | 400 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 419 } | 434 } |
| 420 } | 435 } |
| 421 | 436 |
| 422 | 437 |
| 423 void FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const { | 438 void FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const { |
| 424 if (lit->IsSmi()) { | 439 if (lit->IsSmi()) { |
| 425 __ SafePush(Immediate(lit)); | 440 __ SafePush(Immediate(lit)); |
| 426 } else { | 441 } else { |
| 427 __ push(Immediate(lit)); | 442 __ push(Immediate(lit)); |
| 428 } | 443 } |
| 444 codegen()->increment_stack_height(); |
| 429 } | 445 } |
| 430 | 446 |
| 431 | 447 |
| 432 void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const { | 448 void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const { |
| 433 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, | 449 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, |
| 434 true, | 450 true, |
| 435 true_label_, | 451 true_label_, |
| 436 false_label_); | 452 false_label_); |
| 437 ASSERT(!lit->IsUndetectableObject()); // There are no undetectable literals. | 453 ASSERT(!lit->IsUndetectableObject()); // There are no undetectable literals. |
| 438 if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) { | 454 if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) { |
| (...skipping 17 matching lines...) Expand all Loading... |
| 456 __ mov(result_register(), lit); | 472 __ mov(result_register(), lit); |
| 457 codegen()->DoTest(this); | 473 codegen()->DoTest(this); |
| 458 } | 474 } |
| 459 } | 475 } |
| 460 | 476 |
| 461 | 477 |
| 462 void FullCodeGenerator::EffectContext::DropAndPlug(int count, | 478 void FullCodeGenerator::EffectContext::DropAndPlug(int count, |
| 463 Register reg) const { | 479 Register reg) const { |
| 464 ASSERT(count > 0); | 480 ASSERT(count > 0); |
| 465 __ Drop(count); | 481 __ Drop(count); |
| 482 codegen()->decrement_stack_height(count); |
| 466 } | 483 } |
| 467 | 484 |
| 468 | 485 |
| 469 void FullCodeGenerator::AccumulatorValueContext::DropAndPlug( | 486 void FullCodeGenerator::AccumulatorValueContext::DropAndPlug( |
| 470 int count, | 487 int count, |
| 471 Register reg) const { | 488 Register reg) const { |
| 472 ASSERT(count > 0); | 489 ASSERT(count > 0); |
| 473 __ Drop(count); | 490 __ Drop(count); |
| 474 __ Move(result_register(), reg); | 491 __ Move(result_register(), reg); |
| 492 codegen()->decrement_stack_height(count); |
| 475 } | 493 } |
| 476 | 494 |
| 477 | 495 |
| 478 void FullCodeGenerator::StackValueContext::DropAndPlug(int count, | 496 void FullCodeGenerator::StackValueContext::DropAndPlug(int count, |
| 479 Register reg) const { | 497 Register reg) const { |
| 480 ASSERT(count > 0); | 498 ASSERT(count > 0); |
| 481 if (count > 1) __ Drop(count - 1); | 499 if (count > 1) __ Drop(count - 1); |
| 482 __ mov(Operand(esp, 0), reg); | 500 __ mov(Operand(esp, 0), reg); |
| 501 codegen()->decrement_stack_height(count - 1); |
| 483 } | 502 } |
| 484 | 503 |
| 485 | 504 |
| 486 void FullCodeGenerator::TestContext::DropAndPlug(int count, | 505 void FullCodeGenerator::TestContext::DropAndPlug(int count, |
| 487 Register reg) const { | 506 Register reg) const { |
| 488 ASSERT(count > 0); | 507 ASSERT(count > 0); |
| 489 // For simplicity we always test the accumulator register. | 508 // For simplicity we always test the accumulator register. |
| 490 __ Drop(count); | 509 __ Drop(count); |
| 491 __ Move(result_register(), reg); | 510 __ Move(result_register(), reg); |
| 492 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); | 511 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); |
| 493 codegen()->DoTest(this); | 512 codegen()->DoTest(this); |
| 513 codegen()->decrement_stack_height(count); |
| 494 } | 514 } |
| 495 | 515 |
| 496 | 516 |
| 497 void FullCodeGenerator::EffectContext::Plug(Label* materialize_true, | 517 void FullCodeGenerator::EffectContext::Plug(Label* materialize_true, |
| 498 Label* materialize_false) const { | 518 Label* materialize_false) const { |
| 499 ASSERT(materialize_true == materialize_false); | 519 ASSERT(materialize_true == materialize_false); |
| 500 __ bind(materialize_true); | 520 __ bind(materialize_true); |
| 501 } | 521 } |
| 502 | 522 |
| 503 | 523 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 517 void FullCodeGenerator::StackValueContext::Plug( | 537 void FullCodeGenerator::StackValueContext::Plug( |
| 518 Label* materialize_true, | 538 Label* materialize_true, |
| 519 Label* materialize_false) const { | 539 Label* materialize_false) const { |
| 520 Label done; | 540 Label done; |
| 521 __ bind(materialize_true); | 541 __ bind(materialize_true); |
| 522 __ push(Immediate(isolate()->factory()->true_value())); | 542 __ push(Immediate(isolate()->factory()->true_value())); |
| 523 __ jmp(&done, Label::kNear); | 543 __ jmp(&done, Label::kNear); |
| 524 __ bind(materialize_false); | 544 __ bind(materialize_false); |
| 525 __ push(Immediate(isolate()->factory()->false_value())); | 545 __ push(Immediate(isolate()->factory()->false_value())); |
| 526 __ bind(&done); | 546 __ bind(&done); |
| 547 codegen()->increment_stack_height(); |
| 527 } | 548 } |
| 528 | 549 |
| 529 | 550 |
| 530 void FullCodeGenerator::TestContext::Plug(Label* materialize_true, | 551 void FullCodeGenerator::TestContext::Plug(Label* materialize_true, |
| 531 Label* materialize_false) const { | 552 Label* materialize_false) const { |
| 532 ASSERT(materialize_true == true_label_); | 553 ASSERT(materialize_true == true_label_); |
| 533 ASSERT(materialize_false == false_label_); | 554 ASSERT(materialize_false == false_label_); |
| 534 } | 555 } |
| 535 | 556 |
| 536 | 557 |
| 537 void FullCodeGenerator::EffectContext::Plug(bool flag) const { | 558 void FullCodeGenerator::EffectContext::Plug(bool flag) const { |
| 538 } | 559 } |
| 539 | 560 |
| 540 | 561 |
| 541 void FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const { | 562 void FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const { |
| 542 Handle<Object> value = flag | 563 Handle<Object> value = flag |
| 543 ? isolate()->factory()->true_value() | 564 ? isolate()->factory()->true_value() |
| 544 : isolate()->factory()->false_value(); | 565 : isolate()->factory()->false_value(); |
| 545 __ mov(result_register(), value); | 566 __ mov(result_register(), value); |
| 546 } | 567 } |
| 547 | 568 |
| 548 | 569 |
| 549 void FullCodeGenerator::StackValueContext::Plug(bool flag) const { | 570 void FullCodeGenerator::StackValueContext::Plug(bool flag) const { |
| 550 Handle<Object> value = flag | 571 Handle<Object> value = flag |
| 551 ? isolate()->factory()->true_value() | 572 ? isolate()->factory()->true_value() |
| 552 : isolate()->factory()->false_value(); | 573 : isolate()->factory()->false_value(); |
| 553 __ push(Immediate(value)); | 574 __ push(Immediate(value)); |
| 575 codegen()->increment_stack_height(); |
| 554 } | 576 } |
| 555 | 577 |
| 556 | 578 |
| 557 void FullCodeGenerator::TestContext::Plug(bool flag) const { | 579 void FullCodeGenerator::TestContext::Plug(bool flag) const { |
| 558 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, | 580 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, |
| 559 true, | 581 true, |
| 560 true_label_, | 582 true_label_, |
| 561 false_label_); | 583 false_label_); |
| 562 if (flag) { | 584 if (flag) { |
| 563 if (true_label_ != fall_through_) __ jmp(true_label_); | 585 if (true_label_ != fall_through_) __ jmp(true_label_); |
| 564 } else { | 586 } else { |
| 565 if (false_label_ != fall_through_) __ jmp(false_label_); | 587 if (false_label_ != fall_through_) __ jmp(false_label_); |
| 566 } | 588 } |
| 567 } | 589 } |
| 568 | 590 |
| 569 | 591 |
| 570 void FullCodeGenerator::DoTest(Expression* condition, | 592 void FullCodeGenerator::DoTest(Expression* condition, |
| 571 Label* if_true, | 593 Label* if_true, |
| 572 Label* if_false, | 594 Label* if_false, |
| 573 Label* fall_through) { | 595 Label* fall_through) { |
| 574 ToBooleanStub stub(result_register()); | 596 ToBooleanStub stub(result_register()); |
| 575 __ push(result_register()); | 597 __ push(result_register()); |
| 576 __ CallStub(&stub); | 598 __ CallStub(&stub, condition->test_id()); |
| 577 __ test(result_register(), Operand(result_register())); | 599 __ test(result_register(), Operand(result_register())); |
| 578 // The stub returns nonzero for true. | 600 // The stub returns nonzero for true. |
| 579 Split(not_zero, if_true, if_false, fall_through); | 601 Split(not_zero, if_true, if_false, fall_through); |
| 580 } | 602 } |
| 581 | 603 |
| 582 | 604 |
| 583 void FullCodeGenerator::Split(Condition cc, | 605 void FullCodeGenerator::Split(Condition cc, |
| 584 Label* if_true, | 606 Label* if_true, |
| 585 Label* if_false, | 607 Label* if_false, |
| 586 Label* fall_through) { | 608 Label* fall_through) { |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 724 __ push(esi); | 746 __ push(esi); |
| 725 __ push(Immediate(variable->name())); | 747 __ push(Immediate(variable->name())); |
| 726 // Declaration nodes are always introduced in one of two modes. | 748 // Declaration nodes are always introduced in one of two modes. |
| 727 ASSERT(mode == Variable::VAR || mode == Variable::CONST); | 749 ASSERT(mode == Variable::VAR || mode == Variable::CONST); |
| 728 PropertyAttributes attr = (mode == Variable::VAR) ? NONE : READ_ONLY; | 750 PropertyAttributes attr = (mode == Variable::VAR) ? NONE : READ_ONLY; |
| 729 __ push(Immediate(Smi::FromInt(attr))); | 751 __ push(Immediate(Smi::FromInt(attr))); |
| 730 // Push initial value, if any. | 752 // Push initial value, if any. |
| 731 // Note: For variables we must not push an initial value (such as | 753 // Note: For variables we must not push an initial value (such as |
| 732 // 'undefined') because we may have a (legal) redeclaration and we | 754 // 'undefined') because we may have a (legal) redeclaration and we |
| 733 // must not destroy the current value. | 755 // must not destroy the current value. |
| 756 increment_stack_height(3); |
| 734 if (mode == Variable::CONST) { | 757 if (mode == Variable::CONST) { |
| 735 __ push(Immediate(isolate()->factory()->the_hole_value())); | 758 __ push(Immediate(isolate()->factory()->the_hole_value())); |
| 759 increment_stack_height(); |
| 736 } else if (function != NULL) { | 760 } else if (function != NULL) { |
| 737 VisitForStackValue(function); | 761 VisitForStackValue(function); |
| 738 } else { | 762 } else { |
| 739 __ push(Immediate(Smi::FromInt(0))); // No initial value! | 763 __ push(Immediate(Smi::FromInt(0))); // No initial value! |
| 764 increment_stack_height(); |
| 740 } | 765 } |
| 741 __ CallRuntime(Runtime::kDeclareContextSlot, 4); | 766 __ CallRuntime(Runtime::kDeclareContextSlot, 4); |
| 767 decrement_stack_height(4); |
| 742 break; | 768 break; |
| 743 } | 769 } |
| 744 } | 770 } |
| 745 | 771 |
| 746 } else if (prop != NULL) { | 772 } else if (prop != NULL) { |
| 747 // A const declaration aliasing a parameter is an illegal redeclaration. | 773 // A const declaration aliasing a parameter is an illegal redeclaration. |
| 748 ASSERT(mode != Variable::CONST); | 774 ASSERT(mode != Variable::CONST); |
| 749 if (function != NULL) { | 775 if (function != NULL) { |
| 750 // We are declaring a function that rewrites to a property. | 776 // We are declaring a function that rewrites to a property. |
| 751 // Use (keyed) IC to set the initial value. We cannot visit the | 777 // Use (keyed) IC to set the initial value. We cannot visit the |
| 752 // rewrite because it's shared and we risk recording duplicate AST | 778 // rewrite because it's shared and we risk recording duplicate AST |
| 753 // IDs for bailouts from optimized code. | 779 // IDs for bailouts from optimized code. |
| 754 ASSERT(prop->obj()->AsVariableProxy() != NULL); | 780 ASSERT(prop->obj()->AsVariableProxy() != NULL); |
| 755 { AccumulatorValueContext for_object(this); | 781 { AccumulatorValueContext for_object(this); |
| 756 EmitVariableLoad(prop->obj()->AsVariableProxy()->var()); | 782 EmitVariableLoad(prop->obj()->AsVariableProxy()); |
| 757 } | 783 } |
| 758 | 784 |
| 759 __ push(eax); | 785 __ push(eax); |
| 786 increment_stack_height(); |
| 760 VisitForAccumulatorValue(function); | 787 VisitForAccumulatorValue(function); |
| 761 __ pop(edx); | 788 __ pop(edx); |
| 789 decrement_stack_height(); |
| 762 | 790 |
| 763 ASSERT(prop->key()->AsLiteral() != NULL && | 791 ASSERT(prop->key()->AsLiteral() != NULL && |
| 764 prop->key()->AsLiteral()->handle()->IsSmi()); | 792 prop->key()->AsLiteral()->handle()->IsSmi()); |
| 765 __ SafeSet(ecx, Immediate(prop->key()->AsLiteral()->handle())); | 793 __ SafeSet(ecx, Immediate(prop->key()->AsLiteral()->handle())); |
| 766 | 794 |
| 767 Handle<Code> ic = is_strict_mode() | 795 Handle<Code> ic = is_strict_mode() |
| 768 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() | 796 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() |
| 769 : isolate()->builtins()->KeyedStoreIC_Initialize(); | 797 : isolate()->builtins()->KeyedStoreIC_Initialize(); |
| 770 __ call(ic); | 798 __ call(ic); |
| 771 } | 799 } |
| (...skipping 15 matching lines...) Expand all Loading... |
| 787 __ CallRuntime(Runtime::kDeclareGlobals, 4); | 815 __ CallRuntime(Runtime::kDeclareGlobals, 4); |
| 788 // Return value is ignored. | 816 // Return value is ignored. |
| 789 } | 817 } |
| 790 | 818 |
| 791 | 819 |
| 792 void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { | 820 void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { |
| 793 Comment cmnt(masm_, "[ SwitchStatement"); | 821 Comment cmnt(masm_, "[ SwitchStatement"); |
| 794 Breakable nested_statement(this, stmt); | 822 Breakable nested_statement(this, stmt); |
| 795 SetStatementPosition(stmt); | 823 SetStatementPosition(stmt); |
| 796 | 824 |
| 825 int switch_clause_stack_height = stack_height(); |
| 797 // Keep the switch value on the stack until a case matches. | 826 // Keep the switch value on the stack until a case matches. |
| 798 VisitForStackValue(stmt->tag()); | 827 VisitForStackValue(stmt->tag()); |
| 799 PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS); | 828 PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS); |
| 800 | 829 |
| 801 ZoneList<CaseClause*>* clauses = stmt->cases(); | 830 ZoneList<CaseClause*>* clauses = stmt->cases(); |
| 802 CaseClause* default_clause = NULL; // Can occur anywhere in the list. | 831 CaseClause* default_clause = NULL; // Can occur anywhere in the list. |
| 803 | 832 |
| 804 Label next_test; // Recycled for each test. | 833 Label next_test; // Recycled for each test. |
| 805 // Compile all the tests with branches to their bodies. | 834 // Compile all the tests with branches to their bodies. |
| 806 for (int i = 0; i < clauses->length(); i++) { | 835 for (int i = 0; i < clauses->length(); i++) { |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 851 // Discard the test value and jump to the default if present, otherwise to | 880 // Discard the test value and jump to the default if present, otherwise to |
| 852 // the end of the statement. | 881 // the end of the statement. |
| 853 __ bind(&next_test); | 882 __ bind(&next_test); |
| 854 __ Drop(1); // Switch value is no longer needed. | 883 __ Drop(1); // Switch value is no longer needed. |
| 855 if (default_clause == NULL) { | 884 if (default_clause == NULL) { |
| 856 __ jmp(nested_statement.break_target()); | 885 __ jmp(nested_statement.break_target()); |
| 857 } else { | 886 } else { |
| 858 __ jmp(default_clause->body_target()); | 887 __ jmp(default_clause->body_target()); |
| 859 } | 888 } |
| 860 | 889 |
| 890 set_stack_height(switch_clause_stack_height); |
| 861 // Compile all the case bodies. | 891 // Compile all the case bodies. |
| 862 for (int i = 0; i < clauses->length(); i++) { | 892 for (int i = 0; i < clauses->length(); i++) { |
| 863 Comment cmnt(masm_, "[ Case body"); | 893 Comment cmnt(masm_, "[ Case body"); |
| 864 CaseClause* clause = clauses->at(i); | 894 CaseClause* clause = clauses->at(i); |
| 865 __ bind(clause->body_target()); | 895 __ bind(clause->body_target()); |
| 866 PrepareForBailoutForId(clause->EntryId(), NO_REGISTERS); | 896 PrepareForBailoutForId(clause->EntryId(), NO_REGISTERS); |
| 867 VisitStatements(clause->statements()); | 897 VisitStatements(clause->statements()); |
| 868 } | 898 } |
| 869 | 899 |
| 870 __ bind(nested_statement.break_target()); | 900 __ bind(nested_statement.break_target()); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 892 // Convert the object to a JS object. | 922 // Convert the object to a JS object. |
| 893 Label convert, done_convert; | 923 Label convert, done_convert; |
| 894 __ JumpIfSmi(eax, &convert, Label::kNear); | 924 __ JumpIfSmi(eax, &convert, Label::kNear); |
| 895 __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx); | 925 __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx); |
| 896 __ j(above_equal, &done_convert, Label::kNear); | 926 __ j(above_equal, &done_convert, Label::kNear); |
| 897 __ bind(&convert); | 927 __ bind(&convert); |
| 898 __ push(eax); | 928 __ push(eax); |
| 899 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); | 929 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); |
| 900 __ bind(&done_convert); | 930 __ bind(&done_convert); |
| 901 __ push(eax); | 931 __ push(eax); |
| 932 increment_stack_height(); |
| 902 | 933 |
| 903 // Check cache validity in generated code. This is a fast case for | 934 // Check cache validity in generated code. This is a fast case for |
| 904 // the JSObject::IsSimpleEnum cache validity checks. If we cannot | 935 // the JSObject::IsSimpleEnum cache validity checks. If we cannot |
| 905 // guarantee cache validity, call the runtime system to check cache | 936 // guarantee cache validity, call the runtime system to check cache |
| 906 // validity or get the property names in a fixed array. | 937 // validity or get the property names in a fixed array. |
| 907 Label next, call_runtime; | 938 Label next, call_runtime; |
| 908 __ mov(ecx, eax); | 939 __ mov(ecx, eax); |
| 909 __ bind(&next); | 940 __ bind(&next); |
| 910 | 941 |
| 911 // Check that there are no elements. Register ecx contains the | 942 // Check that there are no elements. Register ecx contains the |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 975 __ jmp(&loop); | 1006 __ jmp(&loop); |
| 976 | 1007 |
| 977 // We got a fixed array in register eax. Iterate through that. | 1008 // We got a fixed array in register eax. Iterate through that. |
| 978 __ bind(&fixed_array); | 1009 __ bind(&fixed_array); |
| 979 __ push(Immediate(Smi::FromInt(0))); // Map (0) - force slow check. | 1010 __ push(Immediate(Smi::FromInt(0))); // Map (0) - force slow check. |
| 980 __ push(eax); | 1011 __ push(eax); |
| 981 __ mov(eax, FieldOperand(eax, FixedArray::kLengthOffset)); | 1012 __ mov(eax, FieldOperand(eax, FixedArray::kLengthOffset)); |
| 982 __ push(eax); // Fixed array length (as smi). | 1013 __ push(eax); // Fixed array length (as smi). |
| 983 __ push(Immediate(Smi::FromInt(0))); // Initial index. | 1014 __ push(Immediate(Smi::FromInt(0))); // Initial index. |
| 984 | 1015 |
| 1016 increment_stack_height(4); |
| 985 // Generate code for doing the condition check. | 1017 // Generate code for doing the condition check. |
| 986 __ bind(&loop); | 1018 __ bind(&loop); |
| 987 __ mov(eax, Operand(esp, 0 * kPointerSize)); // Get the current index. | 1019 __ mov(eax, Operand(esp, 0 * kPointerSize)); // Get the current index. |
| 988 __ cmp(eax, Operand(esp, 1 * kPointerSize)); // Compare to the array length. | 1020 __ cmp(eax, Operand(esp, 1 * kPointerSize)); // Compare to the array length. |
| 989 __ j(above_equal, loop_statement.break_target()); | 1021 __ j(above_equal, loop_statement.break_target()); |
| 990 | 1022 |
| 991 // Get the current entry of the array into register ebx. | 1023 // Get the current entry of the array into register ebx. |
| 992 __ mov(ebx, Operand(esp, 2 * kPointerSize)); | 1024 __ mov(ebx, Operand(esp, 2 * kPointerSize)); |
| 993 __ mov(ebx, FieldOperand(ebx, eax, times_2, FixedArray::kHeaderSize)); | 1025 __ mov(ebx, FieldOperand(ebx, eax, times_2, FixedArray::kHeaderSize)); |
| 994 | 1026 |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1030 __ bind(loop_statement.continue_target()); | 1062 __ bind(loop_statement.continue_target()); |
| 1031 __ add(Operand(esp, 0 * kPointerSize), Immediate(Smi::FromInt(1))); | 1063 __ add(Operand(esp, 0 * kPointerSize), Immediate(Smi::FromInt(1))); |
| 1032 | 1064 |
| 1033 EmitStackCheck(stmt); | 1065 EmitStackCheck(stmt); |
| 1034 __ jmp(&loop); | 1066 __ jmp(&loop); |
| 1035 | 1067 |
| 1036 // Remove the pointers stored on the stack. | 1068 // Remove the pointers stored on the stack. |
| 1037 __ bind(loop_statement.break_target()); | 1069 __ bind(loop_statement.break_target()); |
| 1038 __ add(Operand(esp), Immediate(5 * kPointerSize)); | 1070 __ add(Operand(esp), Immediate(5 * kPointerSize)); |
| 1039 | 1071 |
| 1072 decrement_stack_height(5); |
| 1040 // Exit and decrement the loop depth. | 1073 // Exit and decrement the loop depth. |
| 1041 __ bind(&exit); | 1074 __ bind(&exit); |
| 1042 decrement_loop_depth(); | 1075 decrement_loop_depth(); |
| 1043 } | 1076 } |
| 1044 | 1077 |
| 1045 | 1078 |
| 1046 void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info, | 1079 void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info, |
| 1047 bool pretenure) { | 1080 bool pretenure) { |
| 1048 // Use the fast case closure allocation code that allocates in new | 1081 // Use the fast case closure allocation code that allocates in new |
| 1049 // space for nested functions that don't need literals cloning. If | 1082 // space for nested functions that don't need literals cloning. If |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1066 ? isolate()->factory()->true_value() | 1099 ? isolate()->factory()->true_value() |
| 1067 : isolate()->factory()->false_value())); | 1100 : isolate()->factory()->false_value())); |
| 1068 __ CallRuntime(Runtime::kNewClosure, 3); | 1101 __ CallRuntime(Runtime::kNewClosure, 3); |
| 1069 } | 1102 } |
| 1070 context()->Plug(eax); | 1103 context()->Plug(eax); |
| 1071 } | 1104 } |
| 1072 | 1105 |
| 1073 | 1106 |
| 1074 void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { | 1107 void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { |
| 1075 Comment cmnt(masm_, "[ VariableProxy"); | 1108 Comment cmnt(masm_, "[ VariableProxy"); |
| 1076 EmitVariableLoad(expr->var()); | 1109 EmitVariableLoad(expr); |
| 1077 } | 1110 } |
| 1078 | 1111 |
| 1079 | 1112 |
| 1080 void FullCodeGenerator::EmitLoadGlobalSlotCheckExtensions( | 1113 void FullCodeGenerator::EmitLoadGlobalSlotCheckExtensions( |
| 1081 Slot* slot, | 1114 Slot* slot, |
| 1082 TypeofState typeof_state, | 1115 TypeofState typeof_state, |
| 1083 Label* slow) { | 1116 Label* slow) { |
| 1084 Register context = esi; | 1117 Register context = esi; |
| 1085 Register temp = edx; | 1118 Register temp = edx; |
| 1086 | 1119 |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1216 isolate()->builtins()->KeyedLoadIC_Initialize(); | 1249 isolate()->builtins()->KeyedLoadIC_Initialize(); |
| 1217 __ call(ic, RelocInfo::CODE_TARGET, GetPropertyId(property)); | 1250 __ call(ic, RelocInfo::CODE_TARGET, GetPropertyId(property)); |
| 1218 __ jmp(done); | 1251 __ jmp(done); |
| 1219 } | 1252 } |
| 1220 } | 1253 } |
| 1221 } | 1254 } |
| 1222 } | 1255 } |
| 1223 } | 1256 } |
| 1224 | 1257 |
| 1225 | 1258 |
| 1226 void FullCodeGenerator::EmitVariableLoad(Variable* var) { | 1259 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) { |
| 1260 // Record position before possible IC call. |
| 1261 SetSourcePosition(proxy->position()); |
| 1262 Variable* var = proxy->var(); |
| 1263 |
| 1227 // Three cases: non-this global variables, lookup slots, and all other | 1264 // Three cases: non-this global variables, lookup slots, and all other |
| 1228 // types of slots. | 1265 // types of slots. |
| 1229 Slot* slot = var->AsSlot(); | 1266 Slot* slot = var->AsSlot(); |
| 1230 ASSERT((var->is_global() && !var->is_this()) == (slot == NULL)); | 1267 ASSERT((var->is_global() && !var->is_this()) == (slot == NULL)); |
| 1231 | 1268 |
| 1232 if (slot == NULL) { | 1269 if (slot == NULL) { |
| 1233 Comment cmnt(masm_, "Global variable"); | 1270 Comment cmnt(masm_, "Global variable"); |
| 1234 // Use inline caching. Variable name is passed in ecx and the global | 1271 // Use inline caching. Variable name is passed in ecx and the global |
| 1235 // object on the stack. | 1272 // object on the stack. |
| 1236 __ mov(eax, GlobalObjectOperand()); | 1273 __ mov(eax, GlobalObjectOperand()); |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1361 | 1398 |
| 1362 for (int i = 0; i < expr->properties()->length(); i++) { | 1399 for (int i = 0; i < expr->properties()->length(); i++) { |
| 1363 ObjectLiteral::Property* property = expr->properties()->at(i); | 1400 ObjectLiteral::Property* property = expr->properties()->at(i); |
| 1364 if (property->IsCompileTimeValue()) continue; | 1401 if (property->IsCompileTimeValue()) continue; |
| 1365 | 1402 |
| 1366 Literal* key = property->key(); | 1403 Literal* key = property->key(); |
| 1367 Expression* value = property->value(); | 1404 Expression* value = property->value(); |
| 1368 if (!result_saved) { | 1405 if (!result_saved) { |
| 1369 __ push(eax); // Save result on the stack | 1406 __ push(eax); // Save result on the stack |
| 1370 result_saved = true; | 1407 result_saved = true; |
| 1408 increment_stack_height(); |
| 1371 } | 1409 } |
| 1372 switch (property->kind()) { | 1410 switch (property->kind()) { |
| 1373 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | 1411 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
| 1374 ASSERT(!CompileTimeValue::IsCompileTimeValue(value)); | 1412 ASSERT(!CompileTimeValue::IsCompileTimeValue(value)); |
| 1375 // Fall through. | 1413 // Fall through. |
| 1376 case ObjectLiteral::Property::COMPUTED: | 1414 case ObjectLiteral::Property::COMPUTED: |
| 1377 if (key->handle()->IsSymbol()) { | 1415 if (key->handle()->IsSymbol()) { |
| 1378 if (property->emit_store()) { | 1416 if (property->emit_store()) { |
| 1379 VisitForAccumulatorValue(value); | 1417 VisitForAccumulatorValue(value); |
| 1380 __ mov(ecx, Immediate(key->handle())); | 1418 __ mov(ecx, Immediate(key->handle())); |
| 1381 __ mov(edx, Operand(esp, 0)); | 1419 __ mov(edx, Operand(esp, 0)); |
| 1382 Handle<Code> ic = is_strict_mode() | 1420 Handle<Code> ic = is_strict_mode() |
| 1383 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 1421 ? isolate()->builtins()->StoreIC_Initialize_Strict() |
| 1384 : isolate()->builtins()->StoreIC_Initialize(); | 1422 : isolate()->builtins()->StoreIC_Initialize(); |
| 1385 __ call(ic, RelocInfo::CODE_TARGET, key->id()); | 1423 __ call(ic, RelocInfo::CODE_TARGET, key->id()); |
| 1386 PrepareForBailoutForId(key->id(), NO_REGISTERS); | 1424 PrepareForBailoutForId(key->id(), NO_REGISTERS); |
| 1387 } else { | 1425 } else { |
| 1388 VisitForEffect(value); | 1426 VisitForEffect(value); |
| 1389 } | 1427 } |
| 1390 break; | 1428 break; |
| 1391 } | 1429 } |
| 1392 // Fall through. | 1430 // Fall through. |
| 1393 case ObjectLiteral::Property::PROTOTYPE: | 1431 case ObjectLiteral::Property::PROTOTYPE: |
| 1394 __ push(Operand(esp, 0)); // Duplicate receiver. | 1432 __ push(Operand(esp, 0)); // Duplicate receiver. |
| 1433 increment_stack_height(); |
| 1395 VisitForStackValue(key); | 1434 VisitForStackValue(key); |
| 1396 VisitForStackValue(value); | 1435 VisitForStackValue(value); |
| 1397 if (property->emit_store()) { | 1436 if (property->emit_store()) { |
| 1398 __ push(Immediate(Smi::FromInt(NONE))); // PropertyAttributes | 1437 __ push(Immediate(Smi::FromInt(NONE))); // PropertyAttributes |
| 1399 __ CallRuntime(Runtime::kSetProperty, 4); | 1438 __ CallRuntime(Runtime::kSetProperty, 4); |
| 1400 } else { | 1439 } else { |
| 1401 __ Drop(3); | 1440 __ Drop(3); |
| 1402 } | 1441 } |
| 1442 decrement_stack_height(3); |
| 1403 break; | 1443 break; |
| 1404 case ObjectLiteral::Property::SETTER: | 1444 case ObjectLiteral::Property::SETTER: |
| 1405 case ObjectLiteral::Property::GETTER: | 1445 case ObjectLiteral::Property::GETTER: |
| 1406 __ push(Operand(esp, 0)); // Duplicate receiver. | 1446 __ push(Operand(esp, 0)); // Duplicate receiver. |
| 1447 increment_stack_height(); |
| 1407 VisitForStackValue(key); | 1448 VisitForStackValue(key); |
| 1408 __ push(Immediate(property->kind() == ObjectLiteral::Property::SETTER ? | 1449 __ push(Immediate(property->kind() == ObjectLiteral::Property::SETTER ? |
| 1409 Smi::FromInt(1) : | 1450 Smi::FromInt(1) : |
| 1410 Smi::FromInt(0))); | 1451 Smi::FromInt(0))); |
| 1452 increment_stack_height(); |
| 1411 VisitForStackValue(value); | 1453 VisitForStackValue(value); |
| 1412 __ CallRuntime(Runtime::kDefineAccessor, 4); | 1454 __ CallRuntime(Runtime::kDefineAccessor, 4); |
| 1455 decrement_stack_height(4); |
| 1413 break; | 1456 break; |
| 1414 default: UNREACHABLE(); | 1457 default: UNREACHABLE(); |
| 1415 } | 1458 } |
| 1416 } | 1459 } |
| 1417 | 1460 |
| 1418 if (expr->has_function()) { | 1461 if (expr->has_function()) { |
| 1419 ASSERT(result_saved); | 1462 ASSERT(result_saved); |
| 1420 __ push(Operand(esp, 0)); | 1463 __ push(Operand(esp, 0)); |
| 1421 __ CallRuntime(Runtime::kToFastProperties, 1); | 1464 __ CallRuntime(Runtime::kToFastProperties, 1); |
| 1422 } | 1465 } |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1465 // If the subexpression is a literal or a simple materialized literal it | 1508 // If the subexpression is a literal or a simple materialized literal it |
| 1466 // is already set in the cloned array. | 1509 // is already set in the cloned array. |
| 1467 if (subexpr->AsLiteral() != NULL || | 1510 if (subexpr->AsLiteral() != NULL || |
| 1468 CompileTimeValue::IsCompileTimeValue(subexpr)) { | 1511 CompileTimeValue::IsCompileTimeValue(subexpr)) { |
| 1469 continue; | 1512 continue; |
| 1470 } | 1513 } |
| 1471 | 1514 |
| 1472 if (!result_saved) { | 1515 if (!result_saved) { |
| 1473 __ push(eax); | 1516 __ push(eax); |
| 1474 result_saved = true; | 1517 result_saved = true; |
| 1518 increment_stack_height(); |
| 1475 } | 1519 } |
| 1476 VisitForAccumulatorValue(subexpr); | 1520 VisitForAccumulatorValue(subexpr); |
| 1477 | 1521 |
| 1478 // Store the subexpression value in the array's elements. | 1522 // Store the subexpression value in the array's elements. |
| 1479 __ mov(ebx, Operand(esp, 0)); // Copy of array literal. | 1523 __ mov(ebx, Operand(esp, 0)); // Copy of array literal. |
| 1480 __ mov(ebx, FieldOperand(ebx, JSObject::kElementsOffset)); | 1524 __ mov(ebx, FieldOperand(ebx, JSObject::kElementsOffset)); |
| 1481 int offset = FixedArray::kHeaderSize + (i * kPointerSize); | 1525 int offset = FixedArray::kHeaderSize + (i * kPointerSize); |
| 1482 __ mov(FieldOperand(ebx, offset), result_register()); | 1526 __ mov(FieldOperand(ebx, offset), result_register()); |
| 1483 | 1527 |
| 1484 // Update the write barrier for the array store. | 1528 // Update the write barrier for the array store. |
| 1485 __ RecordWriteField(ebx, offset, result_register(), ecx, kDontSaveFPRegs); | 1529 __ RecordWriteField(ebx, offset, result_register(), ecx, kDontSaveFPRegs); |
| 1486 | 1530 |
| 1487 PrepareForBailoutForId(expr->GetIdForElement(i), NO_REGISTERS); | 1531 PrepareForBailoutForId(expr->GetIdForElement(i), NO_REGISTERS); |
| 1488 } | 1532 } |
| 1489 | 1533 |
| 1490 if (result_saved) { | 1534 if (result_saved) { |
| 1491 context()->PlugTOS(); | 1535 context()->PlugTOS(); |
| 1492 } else { | 1536 } else { |
| 1493 context()->Plug(eax); | 1537 context()->Plug(eax); |
| 1494 } | 1538 } |
| 1495 } | 1539 } |
| 1496 | 1540 |
| 1497 | 1541 |
| 1498 void FullCodeGenerator::VisitAssignment(Assignment* expr) { | 1542 void FullCodeGenerator::VisitAssignment(Assignment* expr) { |
| 1499 Comment cmnt(masm_, "[ Assignment"); | 1543 Comment cmnt(masm_, "[ Assignment"); |
| 1500 // Invalid left-hand sides are rewritten to have a 'throw ReferenceError' | 1544 // Invalid left-hand sides are rewritten to have a 'throw ReferenceError' |
| 1501 // on the left-hand side. | 1545 // on the left-hand side. |
| 1502 if (!expr->target()->IsValidLeftHandSide()) { | 1546 if (!expr->target()->IsValidLeftHandSide()) { |
| 1503 VisitForEffect(expr->target()); | 1547 ASSERT(expr->target()->AsThrow() != NULL); |
| 1548 VisitInCurrentContext(expr->target()); // Throw does not plug the context |
| 1549 context()->Plug(eax); |
| 1504 return; | 1550 return; |
| 1505 } | 1551 } |
| 1506 | 1552 |
| 1507 // Left-hand side can only be a property, a global or a (parameter or local) | 1553 // Left-hand side can only be a property, a global or a (parameter or local) |
| 1508 // slot. | 1554 // slot. |
| 1509 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; | 1555 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; |
| 1510 LhsKind assign_type = VARIABLE; | 1556 LhsKind assign_type = VARIABLE; |
| 1511 Property* property = expr->target()->AsProperty(); | 1557 Property* property = expr->target()->AsProperty(); |
| 1512 if (property != NULL) { | 1558 if (property != NULL) { |
| 1513 assign_type = (property->key()->IsPropertyName()) | 1559 assign_type = (property->key()->IsPropertyName()) |
| 1514 ? NAMED_PROPERTY | 1560 ? NAMED_PROPERTY |
| 1515 : KEYED_PROPERTY; | 1561 : KEYED_PROPERTY; |
| 1516 } | 1562 } |
| 1517 | 1563 |
| 1518 // Evaluate LHS expression. | 1564 // Evaluate LHS expression. |
| 1519 switch (assign_type) { | 1565 switch (assign_type) { |
| 1520 case VARIABLE: | 1566 case VARIABLE: |
| 1521 // Nothing to do here. | 1567 // Nothing to do here. |
| 1522 break; | 1568 break; |
| 1523 case NAMED_PROPERTY: | 1569 case NAMED_PROPERTY: |
| 1524 if (expr->is_compound()) { | 1570 if (expr->is_compound()) { |
| 1525 // We need the receiver both on the stack and in the accumulator. | 1571 // We need the receiver both on the stack and in the accumulator. |
| 1526 VisitForAccumulatorValue(property->obj()); | 1572 VisitForAccumulatorValue(property->obj()); |
| 1527 __ push(result_register()); | 1573 __ push(result_register()); |
| 1574 increment_stack_height(); |
| 1528 } else { | 1575 } else { |
| 1529 VisitForStackValue(property->obj()); | 1576 VisitForStackValue(property->obj()); |
| 1530 } | 1577 } |
| 1531 break; | 1578 break; |
| 1532 case KEYED_PROPERTY: { | 1579 case KEYED_PROPERTY: { |
| 1533 if (expr->is_compound()) { | 1580 if (expr->is_compound()) { |
| 1534 VisitForStackValue(property->obj()); | 1581 VisitForStackValue(property->obj()); |
| 1535 VisitForAccumulatorValue(property->key()); | 1582 VisitForAccumulatorValue(property->key()); |
| 1536 __ mov(edx, Operand(esp, 0)); | 1583 __ mov(edx, Operand(esp, 0)); |
| 1537 __ push(eax); | 1584 __ push(eax); |
| 1585 increment_stack_height(); |
| 1538 } else { | 1586 } else { |
| 1539 VisitForStackValue(property->obj()); | 1587 VisitForStackValue(property->obj()); |
| 1540 VisitForStackValue(property->key()); | 1588 VisitForStackValue(property->key()); |
| 1541 } | 1589 } |
| 1542 break; | 1590 break; |
| 1543 } | 1591 } |
| 1544 } | 1592 } |
| 1545 | 1593 |
| 1546 // For compound assignments we need another deoptimization point after the | 1594 // For compound assignments we need another deoptimization point after the |
| 1547 // variable/property load. | 1595 // variable/property load. |
| 1548 if (expr->is_compound()) { | 1596 if (expr->is_compound()) { |
| 1549 { AccumulatorValueContext context(this); | 1597 AccumulatorValueContext result_context(this); |
| 1598 { AccumulatorValueContext left_operand_context(this); |
| 1550 switch (assign_type) { | 1599 switch (assign_type) { |
| 1551 case VARIABLE: | 1600 case VARIABLE: |
| 1552 EmitVariableLoad(expr->target()->AsVariableProxy()->var()); | 1601 EmitVariableLoad(expr->target()->AsVariableProxy()); |
| 1553 PrepareForBailout(expr->target(), TOS_REG); | 1602 PrepareForBailout(expr->target(), TOS_REG); |
| 1554 break; | 1603 break; |
| 1555 case NAMED_PROPERTY: | 1604 case NAMED_PROPERTY: |
| 1556 EmitNamedPropertyLoad(property); | 1605 EmitNamedPropertyLoad(property); |
| 1557 PrepareForBailoutForId(expr->CompoundLoadId(), TOS_REG); | 1606 PrepareForBailoutForId(expr->CompoundLoadId(), TOS_REG); |
| 1558 break; | 1607 break; |
| 1559 case KEYED_PROPERTY: | 1608 case KEYED_PROPERTY: |
| 1560 EmitKeyedPropertyLoad(property); | 1609 EmitKeyedPropertyLoad(property); |
| 1561 PrepareForBailoutForId(expr->CompoundLoadId(), TOS_REG); | 1610 PrepareForBailoutForId(expr->CompoundLoadId(), TOS_REG); |
| 1562 break; | 1611 break; |
| 1563 } | 1612 } |
| 1564 } | 1613 } |
| 1565 | 1614 |
| 1566 Token::Value op = expr->binary_op(); | 1615 Token::Value op = expr->binary_op(); |
| 1567 __ push(eax); // Left operand goes on the stack. | 1616 __ push(eax); // Left operand goes on the stack. |
| 1617 increment_stack_height(); |
| 1568 VisitForAccumulatorValue(expr->value()); | 1618 VisitForAccumulatorValue(expr->value()); |
| 1569 | 1619 |
| 1570 OverwriteMode mode = expr->value()->ResultOverwriteAllowed() | 1620 OverwriteMode mode = expr->value()->ResultOverwriteAllowed() |
| 1571 ? OVERWRITE_RIGHT | 1621 ? OVERWRITE_RIGHT |
| 1572 : NO_OVERWRITE; | 1622 : NO_OVERWRITE; |
| 1573 SetSourcePosition(expr->position() + 1); | 1623 SetSourcePosition(expr->position() + 1); |
| 1574 AccumulatorValueContext context(this); | |
| 1575 if (ShouldInlineSmiCase(op)) { | 1624 if (ShouldInlineSmiCase(op)) { |
| 1576 EmitInlineSmiBinaryOp(expr->binary_operation(), | 1625 EmitInlineSmiBinaryOp(expr->binary_operation(), |
| 1577 op, | 1626 op, |
| 1578 mode, | 1627 mode, |
| 1579 expr->target(), | 1628 expr->target(), |
| 1580 expr->value()); | 1629 expr->value()); |
| 1581 } else { | 1630 } else { |
| 1582 EmitBinaryOp(expr->binary_operation(), op, mode); | 1631 EmitBinaryOp(expr->binary_operation(), op, mode); |
| 1583 } | 1632 } |
| 1584 | 1633 |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1628 | 1677 |
| 1629 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, | 1678 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, |
| 1630 Token::Value op, | 1679 Token::Value op, |
| 1631 OverwriteMode mode, | 1680 OverwriteMode mode, |
| 1632 Expression* left, | 1681 Expression* left, |
| 1633 Expression* right) { | 1682 Expression* right) { |
| 1634 // Do combined smi check of the operands. Left operand is on the | 1683 // Do combined smi check of the operands. Left operand is on the |
| 1635 // stack. Right operand is in eax. | 1684 // stack. Right operand is in eax. |
| 1636 Label smi_case, done, stub_call; | 1685 Label smi_case, done, stub_call; |
| 1637 __ pop(edx); | 1686 __ pop(edx); |
| 1687 decrement_stack_height(); |
| 1638 __ mov(ecx, eax); | 1688 __ mov(ecx, eax); |
| 1639 __ or_(eax, Operand(edx)); | 1689 __ or_(eax, Operand(edx)); |
| 1640 JumpPatchSite patch_site(masm_); | 1690 JumpPatchSite patch_site(masm_); |
| 1641 patch_site.EmitJumpIfSmi(eax, &smi_case, Label::kNear); | 1691 patch_site.EmitJumpIfSmi(eax, &smi_case, Label::kNear); |
| 1642 | 1692 |
| 1643 __ bind(&stub_call); | 1693 __ bind(&stub_call); |
| 1644 __ mov(eax, ecx); | 1694 __ mov(eax, ecx); |
| 1645 BinaryOpStub stub(op, mode); | 1695 BinaryOpStub stub(op, mode); |
| 1646 __ call(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id()); | 1696 __ call(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id()); |
| 1647 patch_site.EmitPatchInfo(); | 1697 patch_site.EmitPatchInfo(); |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1719 | 1769 |
| 1720 __ bind(&done); | 1770 __ bind(&done); |
| 1721 context()->Plug(eax); | 1771 context()->Plug(eax); |
| 1722 } | 1772 } |
| 1723 | 1773 |
| 1724 | 1774 |
| 1725 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, | 1775 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, |
| 1726 Token::Value op, | 1776 Token::Value op, |
| 1727 OverwriteMode mode) { | 1777 OverwriteMode mode) { |
| 1728 __ pop(edx); | 1778 __ pop(edx); |
| 1779 decrement_stack_height(); |
| 1729 BinaryOpStub stub(op, mode); | 1780 BinaryOpStub stub(op, mode); |
| 1730 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. | 1781 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. |
| 1731 __ call(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id()); | 1782 __ call(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id()); |
| 1732 patch_site.EmitPatchInfo(); | 1783 patch_site.EmitPatchInfo(); |
| 1733 context()->Plug(eax); | 1784 context()->Plug(eax); |
| 1734 } | 1785 } |
| 1735 | 1786 |
| 1736 | 1787 |
| 1737 void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) { | 1788 void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) { |
| 1738 // Invalid left-hand sides are rewritten to have a 'throw | 1789 // Invalid left-hand sides are rewritten to have a 'throw |
| 1739 // ReferenceError' on the left-hand side. | 1790 // ReferenceError' on the left-hand side. |
| 1740 if (!expr->IsValidLeftHandSide()) { | 1791 if (!expr->IsValidLeftHandSide()) { |
| 1741 VisitForEffect(expr); | 1792 ASSERT(expr->AsThrow() != NULL); |
| 1793 VisitInCurrentContext(expr); // Throw does not plug the context |
| 1794 context()->Plug(eax); |
| 1742 return; | 1795 return; |
| 1743 } | 1796 } |
| 1744 | 1797 |
| 1745 // Left-hand side can only be a property, a global or a (parameter or local) | 1798 // Left-hand side can only be a property, a global or a (parameter or local) |
| 1746 // slot. | 1799 // slot. |
| 1747 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; | 1800 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; |
| 1748 LhsKind assign_type = VARIABLE; | 1801 LhsKind assign_type = VARIABLE; |
| 1749 Property* prop = expr->AsProperty(); | 1802 Property* prop = expr->AsProperty(); |
| 1750 if (prop != NULL) { | 1803 if (prop != NULL) { |
| 1751 assign_type = (prop->key()->IsPropertyName()) | 1804 assign_type = (prop->key()->IsPropertyName()) |
| 1752 ? NAMED_PROPERTY | 1805 ? NAMED_PROPERTY |
| 1753 : KEYED_PROPERTY; | 1806 : KEYED_PROPERTY; |
| 1754 } | 1807 } |
| 1755 | 1808 |
| 1756 switch (assign_type) { | 1809 switch (assign_type) { |
| 1757 case VARIABLE: { | 1810 case VARIABLE: { |
| 1758 Variable* var = expr->AsVariableProxy()->var(); | 1811 Variable* var = expr->AsVariableProxy()->var(); |
| 1759 EffectContext context(this); | 1812 EffectContext context(this); |
| 1760 EmitVariableAssignment(var, Token::ASSIGN); | 1813 EmitVariableAssignment(var, Token::ASSIGN); |
| 1761 break; | 1814 break; |
| 1762 } | 1815 } |
| 1763 case NAMED_PROPERTY: { | 1816 case NAMED_PROPERTY: { |
| 1764 __ push(eax); // Preserve value. | 1817 __ push(eax); // Preserve value. |
| 1818 increment_stack_height(); |
| 1765 VisitForAccumulatorValue(prop->obj()); | 1819 VisitForAccumulatorValue(prop->obj()); |
| 1766 __ mov(edx, eax); | 1820 __ mov(edx, eax); |
| 1767 __ pop(eax); // Restore value. | 1821 __ pop(eax); // Restore value. |
| 1822 decrement_stack_height(); |
| 1768 __ mov(ecx, prop->key()->AsLiteral()->handle()); | 1823 __ mov(ecx, prop->key()->AsLiteral()->handle()); |
| 1769 Handle<Code> ic = is_strict_mode() | 1824 Handle<Code> ic = is_strict_mode() |
| 1770 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 1825 ? isolate()->builtins()->StoreIC_Initialize_Strict() |
| 1771 : isolate()->builtins()->StoreIC_Initialize(); | 1826 : isolate()->builtins()->StoreIC_Initialize(); |
| 1772 __ call(ic); | 1827 __ call(ic); |
| 1773 break; | 1828 break; |
| 1774 } | 1829 } |
| 1775 case KEYED_PROPERTY: { | 1830 case KEYED_PROPERTY: { |
| 1776 __ push(eax); // Preserve value. | 1831 __ push(eax); // Preserve value. |
| 1832 increment_stack_height(); |
| 1777 if (prop->is_synthetic()) { | 1833 if (prop->is_synthetic()) { |
| 1778 ASSERT(prop->obj()->AsVariableProxy() != NULL); | 1834 ASSERT(prop->obj()->AsVariableProxy() != NULL); |
| 1779 ASSERT(prop->key()->AsLiteral() != NULL); | 1835 ASSERT(prop->key()->AsLiteral() != NULL); |
| 1780 { AccumulatorValueContext for_object(this); | 1836 { AccumulatorValueContext for_object(this); |
| 1781 EmitVariableLoad(prop->obj()->AsVariableProxy()->var()); | 1837 EmitVariableLoad(prop->obj()->AsVariableProxy()); |
| 1782 } | 1838 } |
| 1783 __ mov(edx, eax); | 1839 __ mov(edx, eax); |
| 1784 __ SafeSet(ecx, Immediate(prop->key()->AsLiteral()->handle())); | 1840 __ SafeSet(ecx, Immediate(prop->key()->AsLiteral()->handle())); |
| 1785 } else { | 1841 } else { |
| 1786 VisitForStackValue(prop->obj()); | 1842 VisitForStackValue(prop->obj()); |
| 1787 VisitForAccumulatorValue(prop->key()); | 1843 VisitForAccumulatorValue(prop->key()); |
| 1788 __ mov(ecx, eax); | 1844 __ mov(ecx, eax); |
| 1789 __ pop(edx); | 1845 __ pop(edx); |
| 1846 decrement_stack_height(); |
| 1790 } | 1847 } |
| 1791 __ pop(eax); // Restore value. | 1848 __ pop(eax); // Restore value. |
| 1849 decrement_stack_height(); |
| 1792 Handle<Code> ic = is_strict_mode() | 1850 Handle<Code> ic = is_strict_mode() |
| 1793 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() | 1851 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() |
| 1794 : isolate()->builtins()->KeyedStoreIC_Initialize(); | 1852 : isolate()->builtins()->KeyedStoreIC_Initialize(); |
| 1795 __ call(ic); | 1853 __ call(ic); |
| 1796 break; | 1854 break; |
| 1797 } | 1855 } |
| 1798 } | 1856 } |
| 1799 PrepareForBailoutForId(bailout_ast_id, TOS_REG); | 1857 PrepareForBailoutForId(bailout_ast_id, TOS_REG); |
| 1800 context()->Plug(eax); | 1858 context()->Plug(eax); |
| 1801 } | 1859 } |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1899 __ pop(result_register()); | 1957 __ pop(result_register()); |
| 1900 } | 1958 } |
| 1901 | 1959 |
| 1902 // Record source code position before IC call. | 1960 // Record source code position before IC call. |
| 1903 SetSourcePosition(expr->position()); | 1961 SetSourcePosition(expr->position()); |
| 1904 __ mov(ecx, prop->key()->AsLiteral()->handle()); | 1962 __ mov(ecx, prop->key()->AsLiteral()->handle()); |
| 1905 if (expr->ends_initialization_block()) { | 1963 if (expr->ends_initialization_block()) { |
| 1906 __ mov(edx, Operand(esp, 0)); | 1964 __ mov(edx, Operand(esp, 0)); |
| 1907 } else { | 1965 } else { |
| 1908 __ pop(edx); | 1966 __ pop(edx); |
| 1967 decrement_stack_height(); |
| 1909 } | 1968 } |
| 1910 Handle<Code> ic = is_strict_mode() | 1969 Handle<Code> ic = is_strict_mode() |
| 1911 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 1970 ? isolate()->builtins()->StoreIC_Initialize_Strict() |
| 1912 : isolate()->builtins()->StoreIC_Initialize(); | 1971 : isolate()->builtins()->StoreIC_Initialize(); |
| 1913 __ call(ic, RelocInfo::CODE_TARGET, expr->id()); | 1972 __ call(ic, RelocInfo::CODE_TARGET, expr->id()); |
| 1914 | 1973 |
| 1915 // If the assignment ends an initialization block, revert to fast case. | 1974 // If the assignment ends an initialization block, revert to fast case. |
| 1916 if (expr->ends_initialization_block()) { | 1975 if (expr->ends_initialization_block()) { |
| 1917 __ push(eax); // Result of assignment, saved even if not needed. | 1976 __ push(eax); // Result of assignment, saved even if not needed. |
| 1918 __ push(Operand(esp, kPointerSize)); // Receiver is under value. | 1977 __ push(Operand(esp, kPointerSize)); // Receiver is under value. |
| 1919 __ CallRuntime(Runtime::kToFastProperties, 1); | 1978 __ CallRuntime(Runtime::kToFastProperties, 1); |
| 1920 __ pop(eax); | 1979 __ pop(eax); |
| 1921 __ Drop(1); | 1980 __ Drop(1); |
| 1981 decrement_stack_height(); |
| 1922 } | 1982 } |
| 1923 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 1983 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 1924 context()->Plug(eax); | 1984 context()->Plug(eax); |
| 1925 } | 1985 } |
| 1926 | 1986 |
| 1927 | 1987 |
| 1928 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { | 1988 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { |
| 1929 // Assignment to a property, using a keyed store IC. | 1989 // Assignment to a property, using a keyed store IC. |
| 1930 | 1990 |
| 1931 // If the assignment starts a block of assignments to the same object, | 1991 // If the assignment starts a block of assignments to the same object, |
| 1932 // change to slow case to avoid the quadratic behavior of repeatedly | 1992 // change to slow case to avoid the quadratic behavior of repeatedly |
| 1933 // adding fast properties. | 1993 // adding fast properties. |
| 1934 if (expr->starts_initialization_block()) { | 1994 if (expr->starts_initialization_block()) { |
| 1935 __ push(result_register()); | 1995 __ push(result_register()); |
| 1936 // Receiver is now under the key and value. | 1996 // Receiver is now under the key and value. |
| 1937 __ push(Operand(esp, 2 * kPointerSize)); | 1997 __ push(Operand(esp, 2 * kPointerSize)); |
| 1938 __ CallRuntime(Runtime::kToSlowProperties, 1); | 1998 __ CallRuntime(Runtime::kToSlowProperties, 1); |
| 1939 __ pop(result_register()); | 1999 __ pop(result_register()); |
| 1940 } | 2000 } |
| 1941 | 2001 |
| 1942 __ pop(ecx); | 2002 __ pop(ecx); |
| 2003 decrement_stack_height(); |
| 1943 if (expr->ends_initialization_block()) { | 2004 if (expr->ends_initialization_block()) { |
| 1944 __ mov(edx, Operand(esp, 0)); // Leave receiver on the stack for later. | 2005 __ mov(edx, Operand(esp, 0)); // Leave receiver on the stack for later. |
| 1945 } else { | 2006 } else { |
| 1946 __ pop(edx); | 2007 __ pop(edx); |
| 2008 decrement_stack_height(); |
| 1947 } | 2009 } |
| 1948 // Record source code position before IC call. | 2010 // Record source code position before IC call. |
| 1949 SetSourcePosition(expr->position()); | 2011 SetSourcePosition(expr->position()); |
| 1950 Handle<Code> ic = is_strict_mode() | 2012 Handle<Code> ic = is_strict_mode() |
| 1951 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() | 2013 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() |
| 1952 : isolate()->builtins()->KeyedStoreIC_Initialize(); | 2014 : isolate()->builtins()->KeyedStoreIC_Initialize(); |
| 1953 __ call(ic, RelocInfo::CODE_TARGET, expr->id()); | 2015 __ call(ic, RelocInfo::CODE_TARGET, expr->id()); |
| 1954 | 2016 |
| 1955 // If the assignment ends an initialization block, revert to fast case. | 2017 // If the assignment ends an initialization block, revert to fast case. |
| 1956 if (expr->ends_initialization_block()) { | 2018 if (expr->ends_initialization_block()) { |
| 1957 __ pop(edx); | 2019 __ pop(edx); |
| 1958 __ push(eax); // Result of assignment, saved even if not needed. | 2020 __ push(eax); // Result of assignment, saved even if not needed. |
| 1959 __ push(edx); | 2021 __ push(edx); |
| 1960 __ CallRuntime(Runtime::kToFastProperties, 1); | 2022 __ CallRuntime(Runtime::kToFastProperties, 1); |
| 1961 __ pop(eax); | 2023 __ pop(eax); |
| 2024 decrement_stack_height(); |
| 1962 } | 2025 } |
| 1963 | 2026 |
| 1964 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 2027 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 1965 context()->Plug(eax); | 2028 context()->Plug(eax); |
| 1966 } | 2029 } |
| 1967 | 2030 |
| 1968 | 2031 |
| 1969 void FullCodeGenerator::VisitProperty(Property* expr) { | 2032 void FullCodeGenerator::VisitProperty(Property* expr) { |
| 1970 Comment cmnt(masm_, "[ Property"); | 2033 Comment cmnt(masm_, "[ Property"); |
| 1971 Expression* key = expr->key(); | 2034 Expression* key = expr->key(); |
| 1972 | 2035 |
| 1973 if (key->IsPropertyName()) { | 2036 if (key->IsPropertyName()) { |
| 1974 VisitForAccumulatorValue(expr->obj()); | 2037 VisitForAccumulatorValue(expr->obj()); |
| 1975 EmitNamedPropertyLoad(expr); | 2038 EmitNamedPropertyLoad(expr); |
| 1976 context()->Plug(eax); | 2039 context()->Plug(eax); |
| 1977 } else { | 2040 } else { |
| 1978 VisitForStackValue(expr->obj()); | 2041 VisitForStackValue(expr->obj()); |
| 1979 VisitForAccumulatorValue(expr->key()); | 2042 VisitForAccumulatorValue(expr->key()); |
| 1980 __ pop(edx); | 2043 __ pop(edx); |
| 2044 decrement_stack_height(); |
| 1981 EmitKeyedPropertyLoad(expr); | 2045 EmitKeyedPropertyLoad(expr); |
| 1982 context()->Plug(eax); | 2046 context()->Plug(eax); |
| 1983 } | 2047 } |
| 1984 } | 2048 } |
| 1985 | 2049 |
| 1986 | 2050 |
| 1987 void FullCodeGenerator::EmitCallWithIC(Call* expr, | 2051 void FullCodeGenerator::EmitCallWithIC(Call* expr, |
| 1988 Handle<Object> name, | 2052 Handle<Object> name, |
| 1989 RelocInfo::Mode mode) { | 2053 RelocInfo::Mode mode) { |
| 1990 // Code common for calls using the IC. | 2054 // Code common for calls using the IC. |
| 1991 ZoneList<Expression*>* args = expr->arguments(); | 2055 ZoneList<Expression*>* args = expr->arguments(); |
| 1992 int arg_count = args->length(); | 2056 int arg_count = args->length(); |
| 1993 { PreservePositionScope scope(masm()->positions_recorder()); | 2057 { PreservePositionScope scope(masm()->positions_recorder()); |
| 1994 for (int i = 0; i < arg_count; i++) { | 2058 for (int i = 0; i < arg_count; i++) { |
| 1995 VisitForStackValue(args->at(i)); | 2059 VisitForStackValue(args->at(i)); |
| 1996 } | 2060 } |
| 1997 __ Set(ecx, Immediate(name)); | 2061 __ Set(ecx, Immediate(name)); |
| 1998 } | 2062 } |
| 1999 // Record source position of the IC call. | 2063 // Record source position of the IC call. |
| 2000 SetSourcePosition(expr->position()); | 2064 SetSourcePosition(expr->position()); |
| 2001 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; | 2065 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; |
| 2002 Handle<Code> ic = | 2066 Handle<Code> ic = |
| 2003 isolate()->stub_cache()->ComputeCallInitialize(arg_count, in_loop, mode); | 2067 isolate()->stub_cache()->ComputeCallInitialize(arg_count, in_loop, mode); |
| 2004 __ call(ic, mode, expr->id()); | 2068 __ call(ic, mode, expr->id()); |
| 2005 RecordJSReturnSite(expr); | 2069 RecordJSReturnSite(expr); |
| 2006 // Restore context register. | 2070 // Restore context register. |
| 2007 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 2071 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 2072 decrement_stack_height(arg_count + 1); |
| 2008 context()->Plug(eax); | 2073 context()->Plug(eax); |
| 2009 } | 2074 } |
| 2010 | 2075 |
| 2011 | 2076 |
| 2012 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, | 2077 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, |
| 2013 Expression* key) { | 2078 Expression* key) { |
| 2014 // Load the key. | 2079 // Load the key. |
| 2015 VisitForAccumulatorValue(key); | 2080 VisitForAccumulatorValue(key); |
| 2016 | 2081 |
| 2017 // Swap the name of the function and the receiver on the stack to follow | 2082 // Swap the name of the function and the receiver on the stack to follow |
| 2018 // the calling convention for call ICs. | 2083 // the calling convention for call ICs. |
| 2019 __ pop(ecx); | 2084 __ pop(ecx); |
| 2020 __ push(eax); | 2085 __ push(eax); |
| 2021 __ push(ecx); | 2086 __ push(ecx); |
| 2087 increment_stack_height(); |
| 2022 | 2088 |
| 2023 // Load the arguments. | 2089 // Load the arguments. |
| 2024 ZoneList<Expression*>* args = expr->arguments(); | 2090 ZoneList<Expression*>* args = expr->arguments(); |
| 2025 int arg_count = args->length(); | 2091 int arg_count = args->length(); |
| 2026 { PreservePositionScope scope(masm()->positions_recorder()); | 2092 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2027 for (int i = 0; i < arg_count; i++) { | 2093 for (int i = 0; i < arg_count; i++) { |
| 2028 VisitForStackValue(args->at(i)); | 2094 VisitForStackValue(args->at(i)); |
| 2029 } | 2095 } |
| 2030 } | 2096 } |
| 2031 // Record source position of the IC call. | 2097 // Record source position of the IC call. |
| 2032 SetSourcePosition(expr->position()); | 2098 SetSourcePosition(expr->position()); |
| 2033 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; | 2099 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; |
| 2034 Handle<Code> ic = isolate()->stub_cache()->ComputeKeyedCallInitialize( | 2100 Handle<Code> ic = isolate()->stub_cache()->ComputeKeyedCallInitialize( |
| 2035 arg_count, in_loop); | 2101 arg_count, in_loop); |
| 2036 __ mov(ecx, Operand(esp, (arg_count + 1) * kPointerSize)); // Key. | 2102 __ mov(ecx, Operand(esp, (arg_count + 1) * kPointerSize)); // Key. |
| 2037 __ call(ic, RelocInfo::CODE_TARGET, expr->id()); | 2103 __ call(ic, RelocInfo::CODE_TARGET, expr->id()); |
| 2038 RecordJSReturnSite(expr); | 2104 RecordJSReturnSite(expr); |
| 2039 // Restore context register. | 2105 // Restore context register. |
| 2040 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 2106 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 2107 decrement_stack_height(arg_count + 1); |
| 2041 context()->DropAndPlug(1, eax); // Drop the key still on the stack. | 2108 context()->DropAndPlug(1, eax); // Drop the key still on the stack. |
| 2042 } | 2109 } |
| 2043 | 2110 |
| 2044 | 2111 |
| 2045 void FullCodeGenerator::EmitCallWithStub(Call* expr, CallFunctionFlags flags) { | 2112 void FullCodeGenerator::EmitCallWithStub(Call* expr, CallFunctionFlags flags) { |
| 2046 // Code common for calls using the call stub. | 2113 // Code common for calls using the call stub. |
| 2047 ZoneList<Expression*>* args = expr->arguments(); | 2114 ZoneList<Expression*>* args = expr->arguments(); |
| 2048 int arg_count = args->length(); | 2115 int arg_count = args->length(); |
| 2049 { PreservePositionScope scope(masm()->positions_recorder()); | 2116 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2050 for (int i = 0; i < arg_count; i++) { | 2117 for (int i = 0; i < arg_count; i++) { |
| 2051 VisitForStackValue(args->at(i)); | 2118 VisitForStackValue(args->at(i)); |
| 2052 } | 2119 } |
| 2053 } | 2120 } |
| 2054 // Record source position for debugger. | 2121 // Record source position for debugger. |
| 2055 SetSourcePosition(expr->position()); | 2122 SetSourcePosition(expr->position()); |
| 2056 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; | 2123 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; |
| 2057 CallFunctionStub stub(arg_count, in_loop, flags); | 2124 CallFunctionStub stub(arg_count, in_loop, flags); |
| 2058 __ CallStub(&stub); | 2125 __ CallStub(&stub); |
| 2059 RecordJSReturnSite(expr); | 2126 RecordJSReturnSite(expr); |
| 2060 // Restore context register. | 2127 // Restore context register. |
| 2061 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 2128 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 2129 |
| 2130 decrement_stack_height(arg_count + 1); |
| 2062 context()->DropAndPlug(1, eax); | 2131 context()->DropAndPlug(1, eax); |
| 2063 } | 2132 } |
| 2064 | 2133 |
| 2065 | 2134 |
| 2066 void FullCodeGenerator::EmitResolvePossiblyDirectEval(ResolveEvalFlag flag, | 2135 void FullCodeGenerator::EmitResolvePossiblyDirectEval(ResolveEvalFlag flag, |
| 2067 int arg_count) { | 2136 int arg_count) { |
| 2068 // Push copy of the first argument or undefined if it doesn't exist. | 2137 // Push copy of the first argument or undefined if it doesn't exist. |
| 2069 if (arg_count > 0) { | 2138 if (arg_count > 0) { |
| 2070 __ push(Operand(esp, arg_count * kPointerSize)); | 2139 __ push(Operand(esp, arg_count * kPointerSize)); |
| 2071 } else { | 2140 } else { |
| (...skipping 27 matching lines...) Expand all Loading... |
| 2099 // In a call to eval, we first call %ResolvePossiblyDirectEval to | 2168 // In a call to eval, we first call %ResolvePossiblyDirectEval to |
| 2100 // resolve the function we need to call and the receiver of the | 2169 // resolve the function we need to call and the receiver of the |
| 2101 // call. Then we call the resolved function using the given | 2170 // call. Then we call the resolved function using the given |
| 2102 // arguments. | 2171 // arguments. |
| 2103 ZoneList<Expression*>* args = expr->arguments(); | 2172 ZoneList<Expression*>* args = expr->arguments(); |
| 2104 int arg_count = args->length(); | 2173 int arg_count = args->length(); |
| 2105 { PreservePositionScope pos_scope(masm()->positions_recorder()); | 2174 { PreservePositionScope pos_scope(masm()->positions_recorder()); |
| 2106 VisitForStackValue(fun); | 2175 VisitForStackValue(fun); |
| 2107 // Reserved receiver slot. | 2176 // Reserved receiver slot. |
| 2108 __ push(Immediate(isolate()->factory()->undefined_value())); | 2177 __ push(Immediate(isolate()->factory()->undefined_value())); |
| 2109 | 2178 increment_stack_height(); |
| 2110 // Push the arguments. | 2179 // Push the arguments. |
| 2111 for (int i = 0; i < arg_count; i++) { | 2180 for (int i = 0; i < arg_count; i++) { |
| 2112 VisitForStackValue(args->at(i)); | 2181 VisitForStackValue(args->at(i)); |
| 2113 } | 2182 } |
| 2114 | 2183 |
| 2115 // If we know that eval can only be shadowed by eval-introduced | 2184 // If we know that eval can only be shadowed by eval-introduced |
| 2116 // variables we attempt to load the global eval function directly | 2185 // variables we attempt to load the global eval function directly |
| 2117 // in generated code. If we succeed, there is no need to perform a | 2186 // in generated code. If we succeed, there is no need to perform a |
| 2118 // context lookup in the runtime system. | 2187 // context lookup in the runtime system. |
| 2119 Label done; | 2188 Label done; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 2143 __ mov(Operand(esp, (arg_count + 1) * kPointerSize), eax); | 2212 __ mov(Operand(esp, (arg_count + 1) * kPointerSize), eax); |
| 2144 } | 2213 } |
| 2145 // Record source position for debugger. | 2214 // Record source position for debugger. |
| 2146 SetSourcePosition(expr->position()); | 2215 SetSourcePosition(expr->position()); |
| 2147 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; | 2216 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; |
| 2148 CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_IMPLICIT); | 2217 CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_IMPLICIT); |
| 2149 __ CallStub(&stub); | 2218 __ CallStub(&stub); |
| 2150 RecordJSReturnSite(expr); | 2219 RecordJSReturnSite(expr); |
| 2151 // Restore context register. | 2220 // Restore context register. |
| 2152 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 2221 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 2222 decrement_stack_height(arg_count + 1); // Function is left on the stack. |
| 2153 context()->DropAndPlug(1, eax); | 2223 context()->DropAndPlug(1, eax); |
| 2154 } else if (var != NULL && !var->is_this() && var->is_global()) { | 2224 } else if (var != NULL && !var->is_this() && var->is_global()) { |
| 2155 // Push global object as receiver for the call IC. | 2225 // Push global object as receiver for the call IC. |
| 2156 __ push(GlobalObjectOperand()); | 2226 __ push(GlobalObjectOperand()); |
| 2227 increment_stack_height(); |
| 2157 EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT); | 2228 EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT); |
| 2158 } else if (var != NULL && var->AsSlot() != NULL && | 2229 } else if (var != NULL && var->AsSlot() != NULL && |
| 2159 var->AsSlot()->type() == Slot::LOOKUP) { | 2230 var->AsSlot()->type() == Slot::LOOKUP) { |
| 2160 // Call to a lookup slot (dynamically introduced variable). | 2231 // Call to a lookup slot (dynamically introduced variable). |
| 2161 Label slow, done; | 2232 Label slow, done; |
| 2162 | 2233 |
| 2163 { PreservePositionScope scope(masm()->positions_recorder()); | 2234 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2164 // Generate code for loading from variables potentially shadowed | 2235 // Generate code for loading from variables potentially shadowed |
| 2165 // by eval-introduced variables. | 2236 // by eval-introduced variables. |
| 2166 EmitDynamicLoadFromSlotFastCase(var->AsSlot(), | 2237 EmitDynamicLoadFromSlotFastCase(var->AsSlot(), |
| 2167 NOT_INSIDE_TYPEOF, | 2238 NOT_INSIDE_TYPEOF, |
| 2168 &slow, | 2239 &slow, |
| 2169 &done); | 2240 &done); |
| 2170 } | 2241 } |
| 2171 | 2242 |
| 2172 __ bind(&slow); | 2243 __ bind(&slow); |
| 2173 // Call the runtime to find the function to call (returned in eax) | 2244 // Call the runtime to find the function to call (returned in eax) |
| 2174 // and the object holding it (returned in edx). | 2245 // and the object holding it (returned in edx). |
| 2175 __ push(context_register()); | 2246 __ push(context_register()); |
| 2176 __ push(Immediate(var->name())); | 2247 __ push(Immediate(var->name())); |
| 2177 __ CallRuntime(Runtime::kLoadContextSlot, 2); | 2248 __ CallRuntime(Runtime::kLoadContextSlot, 2); |
| 2178 __ push(eax); // Function. | 2249 __ push(eax); // Function. |
| 2250 increment_stack_height(); |
| 2179 __ push(edx); // Receiver. | 2251 __ push(edx); // Receiver. |
| 2252 increment_stack_height(); |
| 2180 | 2253 |
| 2181 // If fast case code has been generated, emit code to push the | 2254 // If fast case code has been generated, emit code to push the |
| 2182 // function and receiver and have the slow path jump around this | 2255 // function and receiver and have the slow path jump around this |
| 2183 // code. | 2256 // code. |
| 2184 if (done.is_linked()) { | 2257 if (done.is_linked()) { |
| 2185 Label call; | 2258 Label call; |
| 2186 __ jmp(&call); | 2259 __ jmp(&call); |
| 2187 __ bind(&done); | 2260 __ bind(&done); |
| 2188 // Push function. | 2261 // Push function. Stack height already incremented in slow case above. |
| 2189 __ push(eax); | 2262 __ push(eax); |
| 2190 // The receiver is implicitly the global receiver. Indicate this | 2263 // The receiver is implicitly the global receiver. Indicate this |
| 2191 // by passing the hole to the call function stub. | 2264 // by passing the hole to the call function stub. |
| 2192 __ push(Immediate(isolate()->factory()->the_hole_value())); | 2265 __ push(Immediate(isolate()->factory()->the_hole_value())); |
| 2193 __ bind(&call); | 2266 __ bind(&call); |
| 2194 } | 2267 } |
| 2195 | 2268 |
| 2196 // The receiver is either the global receiver or an object found | 2269 // The receiver is either the global receiver or an object found |
| 2197 // by LoadContextSlot. That object could be the hole if the | 2270 // by LoadContextSlot. That object could be the hole if the |
| 2198 // receiver is implicitly the global object. | 2271 // receiver is implicitly the global object. |
| (...skipping 25 matching lines...) Expand all Loading... |
| 2224 ASSERT(prop->key()->AsLiteral()->handle()->IsSmi()); | 2297 ASSERT(prop->key()->AsLiteral()->handle()->IsSmi()); |
| 2225 __ mov(eax, prop->key()->AsLiteral()->handle()); | 2298 __ mov(eax, prop->key()->AsLiteral()->handle()); |
| 2226 | 2299 |
| 2227 // Record source code position for IC call. | 2300 // Record source code position for IC call. |
| 2228 SetSourcePosition(prop->position()); | 2301 SetSourcePosition(prop->position()); |
| 2229 | 2302 |
| 2230 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); | 2303 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); |
| 2231 __ call(ic, RelocInfo::CODE_TARGET, GetPropertyId(prop)); | 2304 __ call(ic, RelocInfo::CODE_TARGET, GetPropertyId(prop)); |
| 2232 // Push result (function). | 2305 // Push result (function). |
| 2233 __ push(eax); | 2306 __ push(eax); |
| 2307 increment_stack_height(); |
| 2234 // Push Global receiver. | 2308 // Push Global receiver. |
| 2235 __ mov(ecx, GlobalObjectOperand()); | 2309 __ mov(ecx, GlobalObjectOperand()); |
| 2236 __ push(FieldOperand(ecx, GlobalObject::kGlobalReceiverOffset)); | 2310 __ push(FieldOperand(ecx, GlobalObject::kGlobalReceiverOffset)); |
| 2311 increment_stack_height(); |
| 2237 EmitCallWithStub(expr, NO_CALL_FUNCTION_FLAGS); | 2312 EmitCallWithStub(expr, NO_CALL_FUNCTION_FLAGS); |
| 2238 } else { | 2313 } else { |
| 2239 { PreservePositionScope scope(masm()->positions_recorder()); | 2314 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2240 VisitForStackValue(prop->obj()); | 2315 VisitForStackValue(prop->obj()); |
| 2241 } | 2316 } |
| 2242 EmitKeyedCallWithIC(expr, prop->key()); | 2317 EmitKeyedCallWithIC(expr, prop->key()); |
| 2243 } | 2318 } |
| 2244 } | 2319 } |
| 2245 } else { | 2320 } else { |
| 2246 { PreservePositionScope scope(masm()->positions_recorder()); | 2321 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2247 VisitForStackValue(fun); | 2322 VisitForStackValue(fun); |
| 2248 } | 2323 } |
| 2249 // Load global receiver object. | 2324 // Load global receiver object. |
| 2250 __ mov(ebx, GlobalObjectOperand()); | 2325 __ mov(ebx, GlobalObjectOperand()); |
| 2251 __ push(FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset)); | 2326 __ push(FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset)); |
| 2327 increment_stack_height(); |
| 2252 // Emit function call. | 2328 // Emit function call. |
| 2253 EmitCallWithStub(expr, NO_CALL_FUNCTION_FLAGS); | 2329 EmitCallWithStub(expr, NO_CALL_FUNCTION_FLAGS); |
| 2254 } | 2330 } |
| 2255 | 2331 |
| 2256 #ifdef DEBUG | 2332 #ifdef DEBUG |
| 2257 // RecordJSReturnSite should have been called. | 2333 // RecordJSReturnSite should have been called. |
| 2258 ASSERT(expr->return_is_recorded_); | 2334 ASSERT(expr->return_is_recorded_); |
| 2259 #endif | 2335 #endif |
| 2260 } | 2336 } |
| 2261 | 2337 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 2282 // constructor invocation. | 2358 // constructor invocation. |
| 2283 SetSourcePosition(expr->position()); | 2359 SetSourcePosition(expr->position()); |
| 2284 | 2360 |
| 2285 // Load function and argument count into edi and eax. | 2361 // Load function and argument count into edi and eax. |
| 2286 __ SafeSet(eax, Immediate(arg_count)); | 2362 __ SafeSet(eax, Immediate(arg_count)); |
| 2287 __ mov(edi, Operand(esp, arg_count * kPointerSize)); | 2363 __ mov(edi, Operand(esp, arg_count * kPointerSize)); |
| 2288 | 2364 |
| 2289 Handle<Code> construct_builtin = | 2365 Handle<Code> construct_builtin = |
| 2290 isolate()->builtins()->JSConstructCall(); | 2366 isolate()->builtins()->JSConstructCall(); |
| 2291 __ call(construct_builtin, RelocInfo::CONSTRUCT_CALL); | 2367 __ call(construct_builtin, RelocInfo::CONSTRUCT_CALL); |
| 2368 |
| 2369 decrement_stack_height(arg_count + 1); |
| 2292 context()->Plug(eax); | 2370 context()->Plug(eax); |
| 2293 } | 2371 } |
| 2294 | 2372 |
| 2295 | 2373 |
| 2296 void FullCodeGenerator::EmitIsSmi(ZoneList<Expression*>* args) { | 2374 void FullCodeGenerator::EmitIsSmi(ZoneList<Expression*>* args) { |
| 2297 ASSERT(args->length() == 1); | 2375 ASSERT(args->length() == 1); |
| 2298 | 2376 |
| 2299 VisitForAccumulatorValue(args->at(0)); | 2377 VisitForAccumulatorValue(args->at(0)); |
| 2300 | 2378 |
| 2301 Label materialize_true, materialize_false; | 2379 Label materialize_true, materialize_false; |
| (...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2594 VisitForAccumulatorValue(args->at(1)); | 2672 VisitForAccumulatorValue(args->at(1)); |
| 2595 | 2673 |
| 2596 Label materialize_true, materialize_false; | 2674 Label materialize_true, materialize_false; |
| 2597 Label* if_true = NULL; | 2675 Label* if_true = NULL; |
| 2598 Label* if_false = NULL; | 2676 Label* if_false = NULL; |
| 2599 Label* fall_through = NULL; | 2677 Label* fall_through = NULL; |
| 2600 context()->PrepareTest(&materialize_true, &materialize_false, | 2678 context()->PrepareTest(&materialize_true, &materialize_false, |
| 2601 &if_true, &if_false, &fall_through); | 2679 &if_true, &if_false, &fall_through); |
| 2602 | 2680 |
| 2603 __ pop(ebx); | 2681 __ pop(ebx); |
| 2682 decrement_stack_height(); |
| 2604 __ cmp(eax, Operand(ebx)); | 2683 __ cmp(eax, Operand(ebx)); |
| 2605 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); | 2684 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); |
| 2606 Split(equal, if_true, if_false, fall_through); | 2685 Split(equal, if_true, if_false, fall_through); |
| 2607 | 2686 |
| 2608 context()->Plug(if_true, if_false); | 2687 context()->Plug(if_true, if_false); |
| 2609 } | 2688 } |
| 2610 | 2689 |
| 2611 | 2690 |
| 2612 void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) { | 2691 void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) { |
| 2613 ASSERT(args->length() == 1); | 2692 ASSERT(args->length() == 1); |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2704 | 2783 |
| 2705 void FullCodeGenerator::EmitLog(ZoneList<Expression*>* args) { | 2784 void FullCodeGenerator::EmitLog(ZoneList<Expression*>* args) { |
| 2706 // Conditionally generate a log call. | 2785 // Conditionally generate a log call. |
| 2707 // Args: | 2786 // Args: |
| 2708 // 0 (literal string): The type of logging (corresponds to the flags). | 2787 // 0 (literal string): The type of logging (corresponds to the flags). |
| 2709 // This is used to determine whether or not to generate the log call. | 2788 // This is used to determine whether or not to generate the log call. |
| 2710 // 1 (string): Format string. Access the string at argument index 2 | 2789 // 1 (string): Format string. Access the string at argument index 2 |
| 2711 // with '%2s' (see Logger::LogRuntime for all the formats). | 2790 // with '%2s' (see Logger::LogRuntime for all the formats). |
| 2712 // 2 (array): Arguments to the format string. | 2791 // 2 (array): Arguments to the format string. |
| 2713 ASSERT_EQ(args->length(), 3); | 2792 ASSERT_EQ(args->length(), 3); |
| 2714 #ifdef ENABLE_LOGGING_AND_PROFILING | |
| 2715 if (CodeGenerator::ShouldGenerateLog(args->at(0))) { | 2793 if (CodeGenerator::ShouldGenerateLog(args->at(0))) { |
| 2716 VisitForStackValue(args->at(1)); | 2794 VisitForStackValue(args->at(1)); |
| 2717 VisitForStackValue(args->at(2)); | 2795 VisitForStackValue(args->at(2)); |
| 2718 __ CallRuntime(Runtime::kLog, 2); | 2796 __ CallRuntime(Runtime::kLog, 2); |
| 2797 decrement_stack_height(2); |
| 2719 } | 2798 } |
| 2720 #endif | |
| 2721 // Finally, we're expected to leave a value on the top of the stack. | 2799 // Finally, we're expected to leave a value on the top of the stack. |
| 2722 __ mov(eax, isolate()->factory()->undefined_value()); | 2800 __ mov(eax, isolate()->factory()->undefined_value()); |
| 2723 context()->Plug(eax); | 2801 context()->Plug(eax); |
| 2724 } | 2802 } |
| 2725 | 2803 |
| 2726 | 2804 |
| 2727 void FullCodeGenerator::EmitRandomHeapNumber(ZoneList<Expression*>* args) { | 2805 void FullCodeGenerator::EmitRandomHeapNumber(ZoneList<Expression*>* args) { |
| 2728 ASSERT(args->length() == 0); | 2806 ASSERT(args->length() == 0); |
| 2729 | 2807 |
| 2730 Label slow_allocate_heapnumber; | 2808 Label slow_allocate_heapnumber; |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2775 | 2853 |
| 2776 | 2854 |
| 2777 void FullCodeGenerator::EmitSubString(ZoneList<Expression*>* args) { | 2855 void FullCodeGenerator::EmitSubString(ZoneList<Expression*>* args) { |
| 2778 // Load the arguments on the stack and call the stub. | 2856 // Load the arguments on the stack and call the stub. |
| 2779 SubStringStub stub; | 2857 SubStringStub stub; |
| 2780 ASSERT(args->length() == 3); | 2858 ASSERT(args->length() == 3); |
| 2781 VisitForStackValue(args->at(0)); | 2859 VisitForStackValue(args->at(0)); |
| 2782 VisitForStackValue(args->at(1)); | 2860 VisitForStackValue(args->at(1)); |
| 2783 VisitForStackValue(args->at(2)); | 2861 VisitForStackValue(args->at(2)); |
| 2784 __ CallStub(&stub); | 2862 __ CallStub(&stub); |
| 2863 decrement_stack_height(3); |
| 2785 context()->Plug(eax); | 2864 context()->Plug(eax); |
| 2786 } | 2865 } |
| 2787 | 2866 |
| 2788 | 2867 |
| 2789 void FullCodeGenerator::EmitRegExpExec(ZoneList<Expression*>* args) { | 2868 void FullCodeGenerator::EmitRegExpExec(ZoneList<Expression*>* args) { |
| 2790 // Load the arguments on the stack and call the stub. | 2869 // Load the arguments on the stack and call the stub. |
| 2791 RegExpExecStub stub; | 2870 RegExpExecStub stub; |
| 2792 ASSERT(args->length() == 4); | 2871 ASSERT(args->length() == 4); |
| 2793 VisitForStackValue(args->at(0)); | 2872 VisitForStackValue(args->at(0)); |
| 2794 VisitForStackValue(args->at(1)); | 2873 VisitForStackValue(args->at(1)); |
| 2795 VisitForStackValue(args->at(2)); | 2874 VisitForStackValue(args->at(2)); |
| 2796 VisitForStackValue(args->at(3)); | 2875 VisitForStackValue(args->at(3)); |
| 2797 __ CallStub(&stub); | 2876 __ CallStub(&stub); |
| 2877 decrement_stack_height(4); |
| 2798 context()->Plug(eax); | 2878 context()->Plug(eax); |
| 2799 } | 2879 } |
| 2800 | 2880 |
| 2801 | 2881 |
| 2802 void FullCodeGenerator::EmitValueOf(ZoneList<Expression*>* args) { | 2882 void FullCodeGenerator::EmitValueOf(ZoneList<Expression*>* args) { |
| 2803 ASSERT(args->length() == 1); | 2883 ASSERT(args->length() == 1); |
| 2804 | 2884 |
| 2805 VisitForAccumulatorValue(args->at(0)); // Load the object. | 2885 VisitForAccumulatorValue(args->at(0)); // Load the object. |
| 2806 | 2886 |
| 2807 Label done; | 2887 Label done; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 2822 ASSERT(args->length() == 2); | 2902 ASSERT(args->length() == 2); |
| 2823 VisitForStackValue(args->at(0)); | 2903 VisitForStackValue(args->at(0)); |
| 2824 VisitForStackValue(args->at(1)); | 2904 VisitForStackValue(args->at(1)); |
| 2825 | 2905 |
| 2826 if (CpuFeatures::IsSupported(SSE2)) { | 2906 if (CpuFeatures::IsSupported(SSE2)) { |
| 2827 MathPowStub stub; | 2907 MathPowStub stub; |
| 2828 __ CallStub(&stub); | 2908 __ CallStub(&stub); |
| 2829 } else { | 2909 } else { |
| 2830 __ CallRuntime(Runtime::kMath_pow, 2); | 2910 __ CallRuntime(Runtime::kMath_pow, 2); |
| 2831 } | 2911 } |
| 2912 decrement_stack_height(2); |
| 2832 context()->Plug(eax); | 2913 context()->Plug(eax); |
| 2833 } | 2914 } |
| 2834 | 2915 |
| 2835 | 2916 |
| 2836 void FullCodeGenerator::EmitSetValueOf(ZoneList<Expression*>* args) { | 2917 void FullCodeGenerator::EmitSetValueOf(ZoneList<Expression*>* args) { |
| 2837 ASSERT(args->length() == 2); | 2918 ASSERT(args->length() == 2); |
| 2838 | 2919 |
| 2839 VisitForStackValue(args->at(0)); // Load the object. | 2920 VisitForStackValue(args->at(0)); // Load the object. |
| 2840 VisitForAccumulatorValue(args->at(1)); // Load the value. | 2921 VisitForAccumulatorValue(args->at(1)); // Load the value. |
| 2841 __ pop(ebx); // eax = value. ebx = object. | 2922 __ pop(ebx); // eax = value. ebx = object. |
| 2923 decrement_stack_height(); |
| 2842 | 2924 |
| 2843 Label done; | 2925 Label done; |
| 2844 // If the object is a smi, return the value. | 2926 // If the object is a smi, return the value. |
| 2845 __ JumpIfSmi(ebx, &done, Label::kNear); | 2927 __ JumpIfSmi(ebx, &done, Label::kNear); |
| 2846 | 2928 |
| 2847 // If the object is not a value type, return the value. | 2929 // If the object is not a value type, return the value. |
| 2848 __ CmpObjectType(ebx, JS_VALUE_TYPE, ecx); | 2930 __ CmpObjectType(ebx, JS_VALUE_TYPE, ecx); |
| 2849 __ j(not_equal, &done, Label::kNear); | 2931 __ j(not_equal, &done, Label::kNear); |
| 2850 | 2932 |
| 2851 // Store the value. | 2933 // Store the value. |
| (...skipping 10 matching lines...) Expand all Loading... |
| 2862 | 2944 |
| 2863 | 2945 |
| 2864 void FullCodeGenerator::EmitNumberToString(ZoneList<Expression*>* args) { | 2946 void FullCodeGenerator::EmitNumberToString(ZoneList<Expression*>* args) { |
| 2865 ASSERT_EQ(args->length(), 1); | 2947 ASSERT_EQ(args->length(), 1); |
| 2866 | 2948 |
| 2867 // Load the argument on the stack and call the stub. | 2949 // Load the argument on the stack and call the stub. |
| 2868 VisitForStackValue(args->at(0)); | 2950 VisitForStackValue(args->at(0)); |
| 2869 | 2951 |
| 2870 NumberToStringStub stub; | 2952 NumberToStringStub stub; |
| 2871 __ CallStub(&stub); | 2953 __ CallStub(&stub); |
| 2954 decrement_stack_height(); |
| 2872 context()->Plug(eax); | 2955 context()->Plug(eax); |
| 2873 } | 2956 } |
| 2874 | 2957 |
| 2875 | 2958 |
| 2876 void FullCodeGenerator::EmitStringCharFromCode(ZoneList<Expression*>* args) { | 2959 void FullCodeGenerator::EmitStringCharFromCode(ZoneList<Expression*>* args) { |
| 2877 ASSERT(args->length() == 1); | 2960 ASSERT(args->length() == 1); |
| 2878 | 2961 |
| 2879 VisitForAccumulatorValue(args->at(0)); | 2962 VisitForAccumulatorValue(args->at(0)); |
| 2880 | 2963 |
| 2881 Label done; | 2964 Label done; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 2896 | 2979 |
| 2897 VisitForStackValue(args->at(0)); | 2980 VisitForStackValue(args->at(0)); |
| 2898 VisitForAccumulatorValue(args->at(1)); | 2981 VisitForAccumulatorValue(args->at(1)); |
| 2899 | 2982 |
| 2900 Register object = ebx; | 2983 Register object = ebx; |
| 2901 Register index = eax; | 2984 Register index = eax; |
| 2902 Register scratch = ecx; | 2985 Register scratch = ecx; |
| 2903 Register result = edx; | 2986 Register result = edx; |
| 2904 | 2987 |
| 2905 __ pop(object); | 2988 __ pop(object); |
| 2989 decrement_stack_height(); |
| 2906 | 2990 |
| 2907 Label need_conversion; | 2991 Label need_conversion; |
| 2908 Label index_out_of_range; | 2992 Label index_out_of_range; |
| 2909 Label done; | 2993 Label done; |
| 2910 StringCharCodeAtGenerator generator(object, | 2994 StringCharCodeAtGenerator generator(object, |
| 2911 index, | 2995 index, |
| 2912 scratch, | 2996 scratch, |
| 2913 result, | 2997 result, |
| 2914 &need_conversion, | 2998 &need_conversion, |
| 2915 &need_conversion, | 2999 &need_conversion, |
| (...skipping 28 matching lines...) Expand all Loading... |
| 2944 VisitForStackValue(args->at(0)); | 3028 VisitForStackValue(args->at(0)); |
| 2945 VisitForAccumulatorValue(args->at(1)); | 3029 VisitForAccumulatorValue(args->at(1)); |
| 2946 | 3030 |
| 2947 Register object = ebx; | 3031 Register object = ebx; |
| 2948 Register index = eax; | 3032 Register index = eax; |
| 2949 Register scratch1 = ecx; | 3033 Register scratch1 = ecx; |
| 2950 Register scratch2 = edx; | 3034 Register scratch2 = edx; |
| 2951 Register result = eax; | 3035 Register result = eax; |
| 2952 | 3036 |
| 2953 __ pop(object); | 3037 __ pop(object); |
| 3038 decrement_stack_height(); |
| 2954 | 3039 |
| 2955 Label need_conversion; | 3040 Label need_conversion; |
| 2956 Label index_out_of_range; | 3041 Label index_out_of_range; |
| 2957 Label done; | 3042 Label done; |
| 2958 StringCharAtGenerator generator(object, | 3043 StringCharAtGenerator generator(object, |
| 2959 index, | 3044 index, |
| 2960 scratch1, | 3045 scratch1, |
| 2961 scratch2, | 3046 scratch2, |
| 2962 result, | 3047 result, |
| 2963 &need_conversion, | 3048 &need_conversion, |
| (...skipping 24 matching lines...) Expand all Loading... |
| 2988 | 3073 |
| 2989 | 3074 |
| 2990 void FullCodeGenerator::EmitStringAdd(ZoneList<Expression*>* args) { | 3075 void FullCodeGenerator::EmitStringAdd(ZoneList<Expression*>* args) { |
| 2991 ASSERT_EQ(2, args->length()); | 3076 ASSERT_EQ(2, args->length()); |
| 2992 | 3077 |
| 2993 VisitForStackValue(args->at(0)); | 3078 VisitForStackValue(args->at(0)); |
| 2994 VisitForStackValue(args->at(1)); | 3079 VisitForStackValue(args->at(1)); |
| 2995 | 3080 |
| 2996 StringAddStub stub(NO_STRING_ADD_FLAGS); | 3081 StringAddStub stub(NO_STRING_ADD_FLAGS); |
| 2997 __ CallStub(&stub); | 3082 __ CallStub(&stub); |
| 3083 decrement_stack_height(2); |
| 2998 context()->Plug(eax); | 3084 context()->Plug(eax); |
| 2999 } | 3085 } |
| 3000 | 3086 |
| 3001 | 3087 |
| 3002 void FullCodeGenerator::EmitStringCompare(ZoneList<Expression*>* args) { | 3088 void FullCodeGenerator::EmitStringCompare(ZoneList<Expression*>* args) { |
| 3003 ASSERT_EQ(2, args->length()); | 3089 ASSERT_EQ(2, args->length()); |
| 3004 | 3090 |
| 3005 VisitForStackValue(args->at(0)); | 3091 VisitForStackValue(args->at(0)); |
| 3006 VisitForStackValue(args->at(1)); | 3092 VisitForStackValue(args->at(1)); |
| 3007 | 3093 |
| 3008 StringCompareStub stub; | 3094 StringCompareStub stub; |
| 3009 __ CallStub(&stub); | 3095 __ CallStub(&stub); |
| 3096 decrement_stack_height(2); |
| 3010 context()->Plug(eax); | 3097 context()->Plug(eax); |
| 3011 } | 3098 } |
| 3012 | 3099 |
| 3013 | 3100 |
| 3014 void FullCodeGenerator::EmitMathSin(ZoneList<Expression*>* args) { | 3101 void FullCodeGenerator::EmitMathSin(ZoneList<Expression*>* args) { |
| 3015 // Load the argument on the stack and call the stub. | 3102 // Load the argument on the stack and call the stub. |
| 3016 TranscendentalCacheStub stub(TranscendentalCache::SIN, | 3103 TranscendentalCacheStub stub(TranscendentalCache::SIN, |
| 3017 TranscendentalCacheStub::TAGGED); | 3104 TranscendentalCacheStub::TAGGED); |
| 3018 ASSERT(args->length() == 1); | 3105 ASSERT(args->length() == 1); |
| 3019 VisitForStackValue(args->at(0)); | 3106 VisitForStackValue(args->at(0)); |
| 3020 __ CallStub(&stub); | 3107 __ CallStub(&stub); |
| 3108 decrement_stack_height(); |
| 3021 context()->Plug(eax); | 3109 context()->Plug(eax); |
| 3022 } | 3110 } |
| 3023 | 3111 |
| 3024 | 3112 |
| 3025 void FullCodeGenerator::EmitMathCos(ZoneList<Expression*>* args) { | 3113 void FullCodeGenerator::EmitMathCos(ZoneList<Expression*>* args) { |
| 3026 // Load the argument on the stack and call the stub. | 3114 // Load the argument on the stack and call the stub. |
| 3027 TranscendentalCacheStub stub(TranscendentalCache::COS, | 3115 TranscendentalCacheStub stub(TranscendentalCache::COS, |
| 3028 TranscendentalCacheStub::TAGGED); | 3116 TranscendentalCacheStub::TAGGED); |
| 3029 ASSERT(args->length() == 1); | 3117 ASSERT(args->length() == 1); |
| 3030 VisitForStackValue(args->at(0)); | 3118 VisitForStackValue(args->at(0)); |
| 3031 __ CallStub(&stub); | 3119 __ CallStub(&stub); |
| 3120 decrement_stack_height(); |
| 3032 context()->Plug(eax); | 3121 context()->Plug(eax); |
| 3033 } | 3122 } |
| 3034 | 3123 |
| 3035 | 3124 |
| 3036 void FullCodeGenerator::EmitMathLog(ZoneList<Expression*>* args) { | 3125 void FullCodeGenerator::EmitMathLog(ZoneList<Expression*>* args) { |
| 3037 // Load the argument on the stack and call the stub. | 3126 // Load the argument on the stack and call the stub. |
| 3038 TranscendentalCacheStub stub(TranscendentalCache::LOG, | 3127 TranscendentalCacheStub stub(TranscendentalCache::LOG, |
| 3039 TranscendentalCacheStub::TAGGED); | 3128 TranscendentalCacheStub::TAGGED); |
| 3040 ASSERT(args->length() == 1); | 3129 ASSERT(args->length() == 1); |
| 3041 VisitForStackValue(args->at(0)); | 3130 VisitForStackValue(args->at(0)); |
| 3042 __ CallStub(&stub); | 3131 __ CallStub(&stub); |
| 3132 decrement_stack_height(); |
| 3043 context()->Plug(eax); | 3133 context()->Plug(eax); |
| 3044 } | 3134 } |
| 3045 | 3135 |
| 3046 | 3136 |
| 3047 void FullCodeGenerator::EmitMathSqrt(ZoneList<Expression*>* args) { | 3137 void FullCodeGenerator::EmitMathSqrt(ZoneList<Expression*>* args) { |
| 3048 // Load the argument on the stack and call the runtime function. | 3138 // Load the argument on the stack and call the runtime function. |
| 3049 ASSERT(args->length() == 1); | 3139 ASSERT(args->length() == 1); |
| 3050 VisitForStackValue(args->at(0)); | 3140 VisitForStackValue(args->at(0)); |
| 3051 __ CallRuntime(Runtime::kMath_sqrt, 1); | 3141 __ CallRuntime(Runtime::kMath_sqrt, 1); |
| 3142 decrement_stack_height(); |
| 3052 context()->Plug(eax); | 3143 context()->Plug(eax); |
| 3053 } | 3144 } |
| 3054 | 3145 |
| 3055 | 3146 |
| 3056 void FullCodeGenerator::EmitCallFunction(ZoneList<Expression*>* args) { | 3147 void FullCodeGenerator::EmitCallFunction(ZoneList<Expression*>* args) { |
| 3057 ASSERT(args->length() >= 2); | 3148 ASSERT(args->length() >= 2); |
| 3058 | 3149 |
| 3059 int arg_count = args->length() - 2; // 2 ~ receiver and function. | 3150 int arg_count = args->length() - 2; // 2 ~ receiver and function. |
| 3060 for (int i = 0; i < arg_count + 1; ++i) { | 3151 for (int i = 0; i < arg_count + 1; ++i) { |
| 3061 VisitForStackValue(args->at(i)); | 3152 VisitForStackValue(args->at(i)); |
| 3062 } | 3153 } |
| 3063 VisitForAccumulatorValue(args->last()); // Function. | 3154 VisitForAccumulatorValue(args->last()); // Function. |
| 3064 | 3155 |
| 3065 // InvokeFunction requires the function in edi. Move it in there. | 3156 // InvokeFunction requires the function in edi. Move it in there. |
| 3066 __ mov(edi, result_register()); | 3157 __ mov(edi, result_register()); |
| 3067 ParameterCount count(arg_count); | 3158 ParameterCount count(arg_count); |
| 3068 __ InvokeFunction(edi, count, CALL_FUNCTION, | 3159 __ InvokeFunction(edi, count, CALL_FUNCTION, |
| 3069 NullCallWrapper(), CALL_AS_METHOD); | 3160 NullCallWrapper(), CALL_AS_METHOD); |
| 3070 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 3161 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 3162 decrement_stack_height(arg_count + 1); |
| 3071 context()->Plug(eax); | 3163 context()->Plug(eax); |
| 3072 } | 3164 } |
| 3073 | 3165 |
| 3074 | 3166 |
| 3075 void FullCodeGenerator::EmitRegExpConstructResult(ZoneList<Expression*>* args) { | 3167 void FullCodeGenerator::EmitRegExpConstructResult(ZoneList<Expression*>* args) { |
| 3076 // Load the arguments on the stack and call the stub. | 3168 // Load the arguments on the stack and call the stub. |
| 3077 RegExpConstructResultStub stub; | 3169 RegExpConstructResultStub stub; |
| 3078 ASSERT(args->length() == 3); | 3170 ASSERT(args->length() == 3); |
| 3079 VisitForStackValue(args->at(0)); | 3171 VisitForStackValue(args->at(0)); |
| 3080 VisitForStackValue(args->at(1)); | 3172 VisitForStackValue(args->at(1)); |
| 3081 VisitForStackValue(args->at(2)); | 3173 VisitForStackValue(args->at(2)); |
| 3082 __ CallStub(&stub); | 3174 __ CallStub(&stub); |
| 3175 decrement_stack_height(3); |
| 3083 context()->Plug(eax); | 3176 context()->Plug(eax); |
| 3084 } | 3177 } |
| 3085 | 3178 |
| 3086 | 3179 |
| 3087 void FullCodeGenerator::EmitSwapElements(ZoneList<Expression*>* args) { | 3180 void FullCodeGenerator::EmitSwapElements(ZoneList<Expression*>* args) { |
| 3088 ASSERT(args->length() == 3); | 3181 ASSERT(args->length() == 3); |
| 3089 VisitForStackValue(args->at(0)); | 3182 VisitForStackValue(args->at(0)); |
| 3090 VisitForStackValue(args->at(1)); | 3183 VisitForStackValue(args->at(1)); |
| 3091 VisitForStackValue(args->at(2)); | 3184 VisitForStackValue(args->at(2)); |
| 3092 Label done; | 3185 Label done; |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3159 | 3252 |
| 3160 // We are done. Drop elements from the stack, and return undefined. | 3253 // We are done. Drop elements from the stack, and return undefined. |
| 3161 __ add(Operand(esp), Immediate(3 * kPointerSize)); | 3254 __ add(Operand(esp), Immediate(3 * kPointerSize)); |
| 3162 __ mov(eax, isolate()->factory()->undefined_value()); | 3255 __ mov(eax, isolate()->factory()->undefined_value()); |
| 3163 __ jmp(&done); | 3256 __ jmp(&done); |
| 3164 | 3257 |
| 3165 __ bind(&slow_case); | 3258 __ bind(&slow_case); |
| 3166 __ CallRuntime(Runtime::kSwapElements, 3); | 3259 __ CallRuntime(Runtime::kSwapElements, 3); |
| 3167 | 3260 |
| 3168 __ bind(&done); | 3261 __ bind(&done); |
| 3262 decrement_stack_height(3); |
| 3169 context()->Plug(eax); | 3263 context()->Plug(eax); |
| 3170 } | 3264 } |
| 3171 | 3265 |
| 3172 | 3266 |
| 3173 void FullCodeGenerator::EmitGetFromCache(ZoneList<Expression*>* args) { | 3267 void FullCodeGenerator::EmitGetFromCache(ZoneList<Expression*>* args) { |
| 3174 ASSERT_EQ(2, args->length()); | 3268 ASSERT_EQ(2, args->length()); |
| 3175 | 3269 |
| 3176 ASSERT_NE(NULL, args->at(0)->AsLiteral()); | 3270 ASSERT_NE(NULL, args->at(0)->AsLiteral()); |
| 3177 int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->handle()))->value(); | 3271 int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->handle()))->value(); |
| 3178 | 3272 |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3244 __ mov(tmp, FieldOperand(left, JSRegExp::kDataOffset)); | 3338 __ mov(tmp, FieldOperand(left, JSRegExp::kDataOffset)); |
| 3245 __ cmp(tmp, FieldOperand(right, JSRegExp::kDataOffset)); | 3339 __ cmp(tmp, FieldOperand(right, JSRegExp::kDataOffset)); |
| 3246 __ j(equal, &ok); | 3340 __ j(equal, &ok); |
| 3247 __ bind(&fail); | 3341 __ bind(&fail); |
| 3248 __ mov(eax, Immediate(isolate()->factory()->false_value())); | 3342 __ mov(eax, Immediate(isolate()->factory()->false_value())); |
| 3249 __ jmp(&done); | 3343 __ jmp(&done); |
| 3250 __ bind(&ok); | 3344 __ bind(&ok); |
| 3251 __ mov(eax, Immediate(isolate()->factory()->true_value())); | 3345 __ mov(eax, Immediate(isolate()->factory()->true_value())); |
| 3252 __ bind(&done); | 3346 __ bind(&done); |
| 3253 | 3347 |
| 3348 decrement_stack_height(); |
| 3254 context()->Plug(eax); | 3349 context()->Plug(eax); |
| 3255 } | 3350 } |
| 3256 | 3351 |
| 3257 | 3352 |
| 3258 void FullCodeGenerator::EmitHasCachedArrayIndex(ZoneList<Expression*>* args) { | 3353 void FullCodeGenerator::EmitHasCachedArrayIndex(ZoneList<Expression*>* args) { |
| 3259 ASSERT(args->length() == 1); | 3354 ASSERT(args->length() == 1); |
| 3260 | 3355 |
| 3261 VisitForAccumulatorValue(args->at(0)); | 3356 VisitForAccumulatorValue(args->at(0)); |
| 3262 | 3357 |
| 3263 if (FLAG_debug_code) { | 3358 if (FLAG_debug_code) { |
| (...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3547 | 3642 |
| 3548 | 3643 |
| 3549 __ bind(&bailout); | 3644 __ bind(&bailout); |
| 3550 __ mov(result_operand, isolate()->factory()->undefined_value()); | 3645 __ mov(result_operand, isolate()->factory()->undefined_value()); |
| 3551 __ bind(&done); | 3646 __ bind(&done); |
| 3552 __ mov(eax, result_operand); | 3647 __ mov(eax, result_operand); |
| 3553 // Drop temp values from the stack, and restore context register. | 3648 // Drop temp values from the stack, and restore context register. |
| 3554 __ add(Operand(esp), Immediate(3 * kPointerSize)); | 3649 __ add(Operand(esp), Immediate(3 * kPointerSize)); |
| 3555 | 3650 |
| 3556 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 3651 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 3652 decrement_stack_height(); |
| 3557 context()->Plug(eax); | 3653 context()->Plug(eax); |
| 3558 } | 3654 } |
| 3559 | 3655 |
| 3560 | 3656 |
| 3561 void FullCodeGenerator::EmitIsNativeOrStrictMode(ZoneList<Expression*>* args) { | 3657 void FullCodeGenerator::EmitIsNativeOrStrictMode(ZoneList<Expression*>* args) { |
| 3562 ASSERT(args->length() == 1); | 3658 ASSERT(args->length() == 1); |
| 3563 | 3659 |
| 3564 // Load the function into eax. | 3660 // Load the function into eax. |
| 3565 VisitForAccumulatorValue(args->at(0)); | 3661 VisitForAccumulatorValue(args->at(0)); |
| 3566 | 3662 |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3599 return; | 3695 return; |
| 3600 } | 3696 } |
| 3601 | 3697 |
| 3602 Comment cmnt(masm_, "[ CallRuntime"); | 3698 Comment cmnt(masm_, "[ CallRuntime"); |
| 3603 ZoneList<Expression*>* args = expr->arguments(); | 3699 ZoneList<Expression*>* args = expr->arguments(); |
| 3604 | 3700 |
| 3605 if (expr->is_jsruntime()) { | 3701 if (expr->is_jsruntime()) { |
| 3606 // Prepare for calling JS runtime function. | 3702 // Prepare for calling JS runtime function. |
| 3607 __ mov(eax, GlobalObjectOperand()); | 3703 __ mov(eax, GlobalObjectOperand()); |
| 3608 __ push(FieldOperand(eax, GlobalObject::kBuiltinsOffset)); | 3704 __ push(FieldOperand(eax, GlobalObject::kBuiltinsOffset)); |
| 3705 increment_stack_height(); |
| 3609 } | 3706 } |
| 3610 | 3707 |
| 3611 // Push the arguments ("left-to-right"). | 3708 // Push the arguments ("left-to-right"). |
| 3612 int arg_count = args->length(); | 3709 int arg_count = args->length(); |
| 3613 for (int i = 0; i < arg_count; i++) { | 3710 for (int i = 0; i < arg_count; i++) { |
| 3614 VisitForStackValue(args->at(i)); | 3711 VisitForStackValue(args->at(i)); |
| 3615 } | 3712 } |
| 3616 | 3713 |
| 3617 if (expr->is_jsruntime()) { | 3714 if (expr->is_jsruntime()) { |
| 3618 // Call the JS runtime function via a call IC. | 3715 // Call the JS runtime function via a call IC. |
| 3619 __ Set(ecx, Immediate(expr->name())); | 3716 __ Set(ecx, Immediate(expr->name())); |
| 3620 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; | 3717 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; |
| 3621 RelocInfo::Mode mode = RelocInfo::CODE_TARGET; | 3718 RelocInfo::Mode mode = RelocInfo::CODE_TARGET; |
| 3622 Handle<Code> ic = isolate()->stub_cache()->ComputeCallInitialize( | 3719 Handle<Code> ic = isolate()->stub_cache()->ComputeCallInitialize( |
| 3623 arg_count, in_loop, mode); | 3720 arg_count, in_loop, mode); |
| 3624 __ call(ic, mode, expr->id()); | 3721 __ call(ic, mode, expr->id()); |
| 3625 // Restore context register. | 3722 // Restore context register. |
| 3626 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 3723 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 3627 } else { | 3724 } else { |
| 3628 // Call the C runtime function. | 3725 // Call the C runtime function. |
| 3629 __ CallRuntime(expr->function(), arg_count); | 3726 __ CallRuntime(expr->function(), arg_count); |
| 3630 } | 3727 } |
| 3728 decrement_stack_height(arg_count); |
| 3729 if (expr->is_jsruntime()) { |
| 3730 decrement_stack_height(); |
| 3731 } |
| 3732 |
| 3631 context()->Plug(eax); | 3733 context()->Plug(eax); |
| 3632 } | 3734 } |
| 3633 | 3735 |
| 3634 | 3736 |
| 3635 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { | 3737 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { |
| 3636 switch (expr->op()) { | 3738 switch (expr->op()) { |
| 3637 case Token::DELETE: { | 3739 case Token::DELETE: { |
| 3638 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); | 3740 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); |
| 3639 Property* prop = expr->expression()->AsProperty(); | 3741 Property* prop = expr->expression()->AsProperty(); |
| 3640 Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); | 3742 Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); |
| 3641 | 3743 |
| 3642 if (prop != NULL) { | 3744 if (prop != NULL) { |
| 3643 if (prop->is_synthetic()) { | 3745 if (prop->is_synthetic()) { |
| 3644 // Result of deleting parameters is false, even when they rewrite | 3746 // Result of deleting parameters is false, even when they rewrite |
| 3645 // to accesses on the arguments object. | 3747 // to accesses on the arguments object. |
| 3646 context()->Plug(false); | 3748 context()->Plug(false); |
| 3647 } else { | 3749 } else { |
| 3648 VisitForStackValue(prop->obj()); | 3750 VisitForStackValue(prop->obj()); |
| 3649 VisitForStackValue(prop->key()); | 3751 VisitForStackValue(prop->key()); |
| 3650 __ push(Immediate(Smi::FromInt(strict_mode_flag()))); | 3752 __ push(Immediate(Smi::FromInt(strict_mode_flag()))); |
| 3651 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); | 3753 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); |
| 3754 decrement_stack_height(2); |
| 3652 context()->Plug(eax); | 3755 context()->Plug(eax); |
| 3653 } | 3756 } |
| 3654 } else if (var != NULL) { | 3757 } else if (var != NULL) { |
| 3655 // Delete of an unqualified identifier is disallowed in strict mode | 3758 // Delete of an unqualified identifier is disallowed in strict mode |
| 3656 // but "delete this" is. | 3759 // but "delete this" is. |
| 3657 ASSERT(strict_mode_flag() == kNonStrictMode || var->is_this()); | 3760 ASSERT(strict_mode_flag() == kNonStrictMode || var->is_this()); |
| 3658 if (var->is_global()) { | 3761 if (var->is_global()) { |
| 3659 __ push(GlobalObjectOperand()); | 3762 __ push(GlobalObjectOperand()); |
| 3660 __ push(Immediate(var->name())); | 3763 __ push(Immediate(var->name())); |
| 3661 __ push(Immediate(Smi::FromInt(kNonStrictMode))); | 3764 __ push(Immediate(Smi::FromInt(kNonStrictMode))); |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3711 } | 3814 } |
| 3712 break; | 3815 break; |
| 3713 } | 3816 } |
| 3714 | 3817 |
| 3715 case Token::TYPEOF: { | 3818 case Token::TYPEOF: { |
| 3716 Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)"); | 3819 Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)"); |
| 3717 { StackValueContext context(this); | 3820 { StackValueContext context(this); |
| 3718 VisitForTypeofValue(expr->expression()); | 3821 VisitForTypeofValue(expr->expression()); |
| 3719 } | 3822 } |
| 3720 __ CallRuntime(Runtime::kTypeof, 1); | 3823 __ CallRuntime(Runtime::kTypeof, 1); |
| 3824 decrement_stack_height(); |
| 3721 context()->Plug(eax); | 3825 context()->Plug(eax); |
| 3722 break; | 3826 break; |
| 3723 } | 3827 } |
| 3724 | 3828 |
| 3725 case Token::ADD: { | 3829 case Token::ADD: { |
| 3726 Comment cmt(masm_, "[ UnaryOperation (ADD)"); | 3830 Comment cmt(masm_, "[ UnaryOperation (ADD)"); |
| 3727 VisitForAccumulatorValue(expr->expression()); | 3831 VisitForAccumulatorValue(expr->expression()); |
| 3728 Label no_conversion; | 3832 Label no_conversion; |
| 3729 __ JumpIfSmi(result_register(), &no_conversion); | 3833 __ JumpIfSmi(result_register(), &no_conversion); |
| 3730 ToNumberStub convert_stub; | 3834 ToNumberStub convert_stub; |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3765 } | 3869 } |
| 3766 | 3870 |
| 3767 | 3871 |
| 3768 void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { | 3872 void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { |
| 3769 Comment cmnt(masm_, "[ CountOperation"); | 3873 Comment cmnt(masm_, "[ CountOperation"); |
| 3770 SetSourcePosition(expr->position()); | 3874 SetSourcePosition(expr->position()); |
| 3771 | 3875 |
| 3772 // Invalid left-hand sides are rewritten to have a 'throw ReferenceError' | 3876 // Invalid left-hand sides are rewritten to have a 'throw ReferenceError' |
| 3773 // as the left-hand side. | 3877 // as the left-hand side. |
| 3774 if (!expr->expression()->IsValidLeftHandSide()) { | 3878 if (!expr->expression()->IsValidLeftHandSide()) { |
| 3775 VisitForEffect(expr->expression()); | 3879 ASSERT(expr->expression()->AsThrow() != NULL); |
| 3880 VisitInCurrentContext(expr->expression()); |
| 3881 // Visiting Throw does not plug the context. |
| 3882 context()->Plug(eax); |
| 3776 return; | 3883 return; |
| 3777 } | 3884 } |
| 3778 | 3885 |
| 3779 // Expression can only be a property, a global or a (parameter or local) | 3886 // Expression can only be a property, a global or a (parameter or local) |
| 3780 // slot. | 3887 // slot. |
| 3781 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; | 3888 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; |
| 3782 LhsKind assign_type = VARIABLE; | 3889 LhsKind assign_type = VARIABLE; |
| 3783 Property* prop = expr->expression()->AsProperty(); | 3890 Property* prop = expr->expression()->AsProperty(); |
| 3784 // In case of a property we use the uninitialized expression context | 3891 // In case of a property we use the uninitialized expression context |
| 3785 // of the key to detect a named property. | 3892 // of the key to detect a named property. |
| 3786 if (prop != NULL) { | 3893 if (prop != NULL) { |
| 3787 assign_type = | 3894 assign_type = |
| 3788 (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY; | 3895 (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY; |
| 3789 } | 3896 } |
| 3790 | 3897 |
| 3791 // Evaluate expression and get value. | 3898 // Evaluate expression and get value. |
| 3792 if (assign_type == VARIABLE) { | 3899 if (assign_type == VARIABLE) { |
| 3793 ASSERT(expr->expression()->AsVariableProxy()->var() != NULL); | 3900 ASSERT(expr->expression()->AsVariableProxy()->var() != NULL); |
| 3794 AccumulatorValueContext context(this); | 3901 AccumulatorValueContext context(this); |
| 3795 EmitVariableLoad(expr->expression()->AsVariableProxy()->var()); | 3902 EmitVariableLoad(expr->expression()->AsVariableProxy()); |
| 3796 } else { | 3903 } else { |
| 3797 // Reserve space for result of postfix operation. | 3904 // Reserve space for result of postfix operation. |
| 3798 if (expr->is_postfix() && !context()->IsEffect()) { | 3905 if (expr->is_postfix() && !context()->IsEffect()) { |
| 3799 __ push(Immediate(Smi::FromInt(0))); | 3906 __ push(Immediate(Smi::FromInt(0))); |
| 3907 increment_stack_height(); |
| 3800 } | 3908 } |
| 3801 if (assign_type == NAMED_PROPERTY) { | 3909 if (assign_type == NAMED_PROPERTY) { |
| 3802 // Put the object both on the stack and in the accumulator. | 3910 // Put the object both on the stack and in the accumulator. |
| 3803 VisitForAccumulatorValue(prop->obj()); | 3911 VisitForAccumulatorValue(prop->obj()); |
| 3804 __ push(eax); | 3912 __ push(eax); |
| 3913 increment_stack_height(); |
| 3805 EmitNamedPropertyLoad(prop); | 3914 EmitNamedPropertyLoad(prop); |
| 3806 } else { | 3915 } else { |
| 3807 VisitForStackValue(prop->obj()); | 3916 VisitForStackValue(prop->obj()); |
| 3808 VisitForAccumulatorValue(prop->key()); | 3917 VisitForAccumulatorValue(prop->key()); |
| 3809 __ mov(edx, Operand(esp, 0)); | 3918 __ mov(edx, Operand(esp, 0)); |
| 3810 __ push(eax); | 3919 __ push(eax); |
| 3920 increment_stack_height(); |
| 3811 EmitKeyedPropertyLoad(prop); | 3921 EmitKeyedPropertyLoad(prop); |
| 3812 } | 3922 } |
| 3813 } | 3923 } |
| 3814 | 3924 |
| 3815 // We need a second deoptimization point after loading the value | 3925 // We need a second deoptimization point after loading the value |
| 3816 // in case evaluating the property load my have a side effect. | 3926 // in case evaluating the property load my have a side effect. |
| 3817 if (assign_type == VARIABLE) { | 3927 if (assign_type == VARIABLE) { |
| 3818 PrepareForBailout(expr->expression(), TOS_REG); | 3928 PrepareForBailout(expr->expression(), TOS_REG); |
| 3819 } else { | 3929 } else { |
| 3820 PrepareForBailoutForId(expr->CountId(), TOS_REG); | 3930 PrepareForBailoutForId(expr->CountId(), TOS_REG); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 3831 | 3941 |
| 3832 // Save result for postfix expressions. | 3942 // Save result for postfix expressions. |
| 3833 if (expr->is_postfix()) { | 3943 if (expr->is_postfix()) { |
| 3834 if (!context()->IsEffect()) { | 3944 if (!context()->IsEffect()) { |
| 3835 // Save the result on the stack. If we have a named or keyed property | 3945 // Save the result on the stack. If we have a named or keyed property |
| 3836 // we store the result under the receiver that is currently on top | 3946 // we store the result under the receiver that is currently on top |
| 3837 // of the stack. | 3947 // of the stack. |
| 3838 switch (assign_type) { | 3948 switch (assign_type) { |
| 3839 case VARIABLE: | 3949 case VARIABLE: |
| 3840 __ push(eax); | 3950 __ push(eax); |
| 3951 increment_stack_height(); |
| 3841 break; | 3952 break; |
| 3842 case NAMED_PROPERTY: | 3953 case NAMED_PROPERTY: |
| 3843 __ mov(Operand(esp, kPointerSize), eax); | 3954 __ mov(Operand(esp, kPointerSize), eax); |
| 3844 break; | 3955 break; |
| 3845 case KEYED_PROPERTY: | 3956 case KEYED_PROPERTY: |
| 3846 __ mov(Operand(esp, 2 * kPointerSize), eax); | 3957 __ mov(Operand(esp, 2 * kPointerSize), eax); |
| 3847 break; | 3958 break; |
| 3848 } | 3959 } |
| 3849 } | 3960 } |
| 3850 } | 3961 } |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3904 // Perform the assignment as if via '='. | 4015 // Perform the assignment as if via '='. |
| 3905 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), | 4016 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
| 3906 Token::ASSIGN); | 4017 Token::ASSIGN); |
| 3907 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 4018 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 3908 context()->Plug(eax); | 4019 context()->Plug(eax); |
| 3909 } | 4020 } |
| 3910 break; | 4021 break; |
| 3911 case NAMED_PROPERTY: { | 4022 case NAMED_PROPERTY: { |
| 3912 __ mov(ecx, prop->key()->AsLiteral()->handle()); | 4023 __ mov(ecx, prop->key()->AsLiteral()->handle()); |
| 3913 __ pop(edx); | 4024 __ pop(edx); |
| 4025 decrement_stack_height(); |
| 3914 Handle<Code> ic = is_strict_mode() | 4026 Handle<Code> ic = is_strict_mode() |
| 3915 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 4027 ? isolate()->builtins()->StoreIC_Initialize_Strict() |
| 3916 : isolate()->builtins()->StoreIC_Initialize(); | 4028 : isolate()->builtins()->StoreIC_Initialize(); |
| 3917 __ call(ic, RelocInfo::CODE_TARGET, expr->id()); | 4029 __ call(ic, RelocInfo::CODE_TARGET, expr->id()); |
| 3918 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 4030 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 3919 if (expr->is_postfix()) { | 4031 if (expr->is_postfix()) { |
| 3920 if (!context()->IsEffect()) { | 4032 if (!context()->IsEffect()) { |
| 3921 context()->PlugTOS(); | 4033 context()->PlugTOS(); |
| 3922 } | 4034 } |
| 3923 } else { | 4035 } else { |
| 3924 context()->Plug(eax); | 4036 context()->Plug(eax); |
| 3925 } | 4037 } |
| 3926 break; | 4038 break; |
| 3927 } | 4039 } |
| 3928 case KEYED_PROPERTY: { | 4040 case KEYED_PROPERTY: { |
| 3929 __ pop(ecx); | 4041 __ pop(ecx); |
| 3930 __ pop(edx); | 4042 __ pop(edx); |
| 4043 decrement_stack_height(); |
| 4044 decrement_stack_height(); |
| 3931 Handle<Code> ic = is_strict_mode() | 4045 Handle<Code> ic = is_strict_mode() |
| 3932 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() | 4046 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() |
| 3933 : isolate()->builtins()->KeyedStoreIC_Initialize(); | 4047 : isolate()->builtins()->KeyedStoreIC_Initialize(); |
| 3934 __ call(ic, RelocInfo::CODE_TARGET, expr->id()); | 4048 __ call(ic, RelocInfo::CODE_TARGET, expr->id()); |
| 3935 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 4049 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 3936 if (expr->is_postfix()) { | 4050 if (expr->is_postfix()) { |
| 3937 // Result is on the stack | 4051 // Result is on the stack |
| 3938 if (!context()->IsEffect()) { | 4052 if (!context()->IsEffect()) { |
| 3939 context()->PlugTOS(); | 4053 context()->PlugTOS(); |
| 3940 } | 4054 } |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4078 context()->Plug(if_true, if_false); | 4192 context()->Plug(if_true, if_false); |
| 4079 return; | 4193 return; |
| 4080 } | 4194 } |
| 4081 | 4195 |
| 4082 Token::Value op = expr->op(); | 4196 Token::Value op = expr->op(); |
| 4083 VisitForStackValue(expr->left()); | 4197 VisitForStackValue(expr->left()); |
| 4084 switch (expr->op()) { | 4198 switch (expr->op()) { |
| 4085 case Token::IN: | 4199 case Token::IN: |
| 4086 VisitForStackValue(expr->right()); | 4200 VisitForStackValue(expr->right()); |
| 4087 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION); | 4201 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION); |
| 4202 decrement_stack_height(2); |
| 4088 PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); | 4203 PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); |
| 4089 __ cmp(eax, isolate()->factory()->true_value()); | 4204 __ cmp(eax, isolate()->factory()->true_value()); |
| 4090 Split(equal, if_true, if_false, fall_through); | 4205 Split(equal, if_true, if_false, fall_through); |
| 4091 break; | 4206 break; |
| 4092 | 4207 |
| 4093 case Token::INSTANCEOF: { | 4208 case Token::INSTANCEOF: { |
| 4094 VisitForStackValue(expr->right()); | 4209 VisitForStackValue(expr->right()); |
| 4095 InstanceofStub stub(InstanceofStub::kNoFlags); | 4210 InstanceofStub stub(InstanceofStub::kNoFlags); |
| 4096 __ CallStub(&stub); | 4211 __ CallStub(&stub); |
| 4212 decrement_stack_height(2); |
| 4097 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); | 4213 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); |
| 4098 __ test(eax, Operand(eax)); | 4214 __ test(eax, Operand(eax)); |
| 4099 // The stub returns 0 for true. | 4215 // The stub returns 0 for true. |
| 4100 Split(zero, if_true, if_false, fall_through); | 4216 Split(zero, if_true, if_false, fall_through); |
| 4101 break; | 4217 break; |
| 4102 } | 4218 } |
| 4103 | 4219 |
| 4104 default: { | 4220 default: { |
| 4105 VisitForAccumulatorValue(expr->right()); | 4221 VisitForAccumulatorValue(expr->right()); |
| 4106 Condition cc = no_condition; | 4222 Condition cc = no_condition; |
| (...skipping 24 matching lines...) Expand all Loading... |
| 4131 break; | 4247 break; |
| 4132 case Token::GTE: | 4248 case Token::GTE: |
| 4133 cc = greater_equal; | 4249 cc = greater_equal; |
| 4134 __ pop(edx); | 4250 __ pop(edx); |
| 4135 break; | 4251 break; |
| 4136 case Token::IN: | 4252 case Token::IN: |
| 4137 case Token::INSTANCEOF: | 4253 case Token::INSTANCEOF: |
| 4138 default: | 4254 default: |
| 4139 UNREACHABLE(); | 4255 UNREACHABLE(); |
| 4140 } | 4256 } |
| 4257 decrement_stack_height(); |
| 4141 | 4258 |
| 4142 bool inline_smi_code = ShouldInlineSmiCase(op); | 4259 bool inline_smi_code = ShouldInlineSmiCase(op); |
| 4143 JumpPatchSite patch_site(masm_); | 4260 JumpPatchSite patch_site(masm_); |
| 4144 if (inline_smi_code) { | 4261 if (inline_smi_code) { |
| 4145 Label slow_case; | 4262 Label slow_case; |
| 4146 __ mov(ecx, Operand(edx)); | 4263 __ mov(ecx, Operand(edx)); |
| 4147 __ or_(ecx, Operand(eax)); | 4264 __ or_(ecx, Operand(eax)); |
| 4148 patch_site.EmitJumpIfNotSmi(ecx, &slow_case, Label::kNear); | 4265 patch_site.EmitJumpIfNotSmi(ecx, &slow_case, Label::kNear); |
| 4149 __ cmp(edx, Operand(eax)); | 4266 __ cmp(edx, Operand(eax)); |
| 4150 Split(cc, if_true, if_false, NULL); | 4267 Split(cc, if_true, if_false, NULL); |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4271 __ add(Operand(edx), Immediate(masm_->CodeObject())); | 4388 __ add(Operand(edx), Immediate(masm_->CodeObject())); |
| 4272 __ jmp(Operand(edx)); | 4389 __ jmp(Operand(edx)); |
| 4273 } | 4390 } |
| 4274 | 4391 |
| 4275 | 4392 |
| 4276 #undef __ | 4393 #undef __ |
| 4277 | 4394 |
| 4278 } } // namespace v8::internal | 4395 } } // namespace v8::internal |
| 4279 | 4396 |
| 4280 #endif // V8_TARGET_ARCH_IA32 | 4397 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |