| 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 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 351 #ifdef ENABLE_DEBUGGER_SUPPORT | 356 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 352 // Check that the size of the code used for returning is large enough | 357 // Check that the size of the code used for returning is large enough |
| 353 // for the debugger's requirements. | 358 // for the debugger's requirements. |
| 354 ASSERT(Assembler::kJSReturnSequenceLength <= | 359 ASSERT(Assembler::kJSReturnSequenceLength <= |
| 355 masm_->SizeOfCodeGeneratedSince(&check_exit_codesize)); | 360 masm_->SizeOfCodeGeneratedSince(&check_exit_codesize)); |
| 356 #endif | 361 #endif |
| 357 } | 362 } |
| 358 } | 363 } |
| 359 | 364 |
| 360 | 365 |
| 366 void FullCodeGenerator::verify_stack_height() { |
| 367 ASSERT(FLAG_verify_stack_height); |
| 368 __ sub(Operand(ebp), Immediate(kPointerSize * stack_height())); |
| 369 __ cmp(ebp, Operand(esp)); |
| 370 __ Assert(equal, "Full codegen stack height not as expected."); |
| 371 __ add(Operand(ebp), Immediate(kPointerSize * stack_height())); |
| 372 } |
| 373 |
| 374 |
| 361 void FullCodeGenerator::EffectContext::Plug(Slot* slot) const { | 375 void FullCodeGenerator::EffectContext::Plug(Slot* slot) const { |
| 362 } | 376 } |
| 363 | 377 |
| 364 | 378 |
| 365 void FullCodeGenerator::AccumulatorValueContext::Plug(Slot* slot) const { | 379 void FullCodeGenerator::AccumulatorValueContext::Plug(Slot* slot) const { |
| 366 MemOperand slot_operand = codegen()->EmitSlotSearch(slot, result_register()); | 380 MemOperand slot_operand = codegen()->EmitSlotSearch(slot, result_register()); |
| 367 __ mov(result_register(), slot_operand); | 381 __ mov(result_register(), slot_operand); |
| 368 } | 382 } |
| 369 | 383 |
| 370 | 384 |
| 371 void FullCodeGenerator::StackValueContext::Plug(Slot* slot) const { | 385 void FullCodeGenerator::StackValueContext::Plug(Slot* slot) const { |
| 372 MemOperand slot_operand = codegen()->EmitSlotSearch(slot, result_register()); | 386 MemOperand slot_operand = codegen()->EmitSlotSearch(slot, result_register()); |
| 373 // Memory operands can be pushed directly. | 387 // Memory operands can be pushed directly. |
| 374 __ push(slot_operand); | 388 __ push(slot_operand); |
| 389 codegen()->increment_stack_height(); |
| 375 } | 390 } |
| 376 | 391 |
| 377 | 392 |
| 378 void FullCodeGenerator::TestContext::Plug(Slot* slot) const { | 393 void FullCodeGenerator::TestContext::Plug(Slot* slot) const { |
| 379 // For simplicity we always test the accumulator register. | 394 // For simplicity we always test the accumulator register. |
| 380 codegen()->Move(result_register(), slot); | 395 codegen()->Move(result_register(), slot); |
| 381 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); | 396 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); |
| 382 codegen()->DoTest(this); | 397 codegen()->DoTest(this); |
| 383 } | 398 } |
| 384 | 399 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 418 } | 433 } |
| 419 } | 434 } |
| 420 | 435 |
| 421 | 436 |
| 422 void FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const { | 437 void FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const { |
| 423 if (lit->IsSmi()) { | 438 if (lit->IsSmi()) { |
| 424 __ SafePush(Immediate(lit)); | 439 __ SafePush(Immediate(lit)); |
| 425 } else { | 440 } else { |
| 426 __ push(Immediate(lit)); | 441 __ push(Immediate(lit)); |
| 427 } | 442 } |
| 443 codegen()->increment_stack_height(); |
| 428 } | 444 } |
| 429 | 445 |
| 430 | 446 |
| 431 void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const { | 447 void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const { |
| 432 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, | 448 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, |
| 433 true, | 449 true, |
| 434 true_label_, | 450 true_label_, |
| 435 false_label_); | 451 false_label_); |
| 436 ASSERT(!lit->IsUndetectableObject()); // There are no undetectable literals. | 452 ASSERT(!lit->IsUndetectableObject()); // There are no undetectable literals. |
| 437 if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) { | 453 if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) { |
| (...skipping 17 matching lines...) Expand all Loading... |
| 455 __ mov(result_register(), lit); | 471 __ mov(result_register(), lit); |
| 456 codegen()->DoTest(this); | 472 codegen()->DoTest(this); |
| 457 } | 473 } |
| 458 } | 474 } |
| 459 | 475 |
| 460 | 476 |
| 461 void FullCodeGenerator::EffectContext::DropAndPlug(int count, | 477 void FullCodeGenerator::EffectContext::DropAndPlug(int count, |
| 462 Register reg) const { | 478 Register reg) const { |
| 463 ASSERT(count > 0); | 479 ASSERT(count > 0); |
| 464 __ Drop(count); | 480 __ Drop(count); |
| 481 codegen()->decrement_stack_height(count); |
| 465 } | 482 } |
| 466 | 483 |
| 467 | 484 |
| 468 void FullCodeGenerator::AccumulatorValueContext::DropAndPlug( | 485 void FullCodeGenerator::AccumulatorValueContext::DropAndPlug( |
| 469 int count, | 486 int count, |
| 470 Register reg) const { | 487 Register reg) const { |
| 471 ASSERT(count > 0); | 488 ASSERT(count > 0); |
| 472 __ Drop(count); | 489 __ Drop(count); |
| 473 __ Move(result_register(), reg); | 490 __ Move(result_register(), reg); |
| 491 codegen()->decrement_stack_height(count); |
| 474 } | 492 } |
| 475 | 493 |
| 476 | 494 |
| 477 void FullCodeGenerator::StackValueContext::DropAndPlug(int count, | 495 void FullCodeGenerator::StackValueContext::DropAndPlug(int count, |
| 478 Register reg) const { | 496 Register reg) const { |
| 479 ASSERT(count > 0); | 497 ASSERT(count > 0); |
| 480 if (count > 1) __ Drop(count - 1); | 498 if (count > 1) __ Drop(count - 1); |
| 481 __ mov(Operand(esp, 0), reg); | 499 __ mov(Operand(esp, 0), reg); |
| 500 codegen()->decrement_stack_height(count - 1); |
| 482 } | 501 } |
| 483 | 502 |
| 484 | 503 |
| 485 void FullCodeGenerator::TestContext::DropAndPlug(int count, | 504 void FullCodeGenerator::TestContext::DropAndPlug(int count, |
| 486 Register reg) const { | 505 Register reg) const { |
| 487 ASSERT(count > 0); | 506 ASSERT(count > 0); |
| 488 // For simplicity we always test the accumulator register. | 507 // For simplicity we always test the accumulator register. |
| 489 __ Drop(count); | 508 __ Drop(count); |
| 490 __ Move(result_register(), reg); | 509 __ Move(result_register(), reg); |
| 491 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); | 510 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); |
| 492 codegen()->DoTest(this); | 511 codegen()->DoTest(this); |
| 512 codegen()->decrement_stack_height(count); |
| 493 } | 513 } |
| 494 | 514 |
| 495 | 515 |
| 496 void FullCodeGenerator::EffectContext::Plug(Label* materialize_true, | 516 void FullCodeGenerator::EffectContext::Plug(Label* materialize_true, |
| 497 Label* materialize_false) const { | 517 Label* materialize_false) const { |
| 498 ASSERT(materialize_true == materialize_false); | 518 ASSERT(materialize_true == materialize_false); |
| 499 __ bind(materialize_true); | 519 __ bind(materialize_true); |
| 500 } | 520 } |
| 501 | 521 |
| 502 | 522 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 516 void FullCodeGenerator::StackValueContext::Plug( | 536 void FullCodeGenerator::StackValueContext::Plug( |
| 517 Label* materialize_true, | 537 Label* materialize_true, |
| 518 Label* materialize_false) const { | 538 Label* materialize_false) const { |
| 519 Label done; | 539 Label done; |
| 520 __ bind(materialize_true); | 540 __ bind(materialize_true); |
| 521 __ push(Immediate(isolate()->factory()->true_value())); | 541 __ push(Immediate(isolate()->factory()->true_value())); |
| 522 __ jmp(&done, Label::kNear); | 542 __ jmp(&done, Label::kNear); |
| 523 __ bind(materialize_false); | 543 __ bind(materialize_false); |
| 524 __ push(Immediate(isolate()->factory()->false_value())); | 544 __ push(Immediate(isolate()->factory()->false_value())); |
| 525 __ bind(&done); | 545 __ bind(&done); |
| 546 codegen()->increment_stack_height(); |
| 526 } | 547 } |
| 527 | 548 |
| 528 | 549 |
| 529 void FullCodeGenerator::TestContext::Plug(Label* materialize_true, | 550 void FullCodeGenerator::TestContext::Plug(Label* materialize_true, |
| 530 Label* materialize_false) const { | 551 Label* materialize_false) const { |
| 531 ASSERT(materialize_true == true_label_); | 552 ASSERT(materialize_true == true_label_); |
| 532 ASSERT(materialize_false == false_label_); | 553 ASSERT(materialize_false == false_label_); |
| 533 } | 554 } |
| 534 | 555 |
| 535 | 556 |
| 536 void FullCodeGenerator::EffectContext::Plug(bool flag) const { | 557 void FullCodeGenerator::EffectContext::Plug(bool flag) const { |
| 537 } | 558 } |
| 538 | 559 |
| 539 | 560 |
| 540 void FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const { | 561 void FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const { |
| 541 Handle<Object> value = flag | 562 Handle<Object> value = flag |
| 542 ? isolate()->factory()->true_value() | 563 ? isolate()->factory()->true_value() |
| 543 : isolate()->factory()->false_value(); | 564 : isolate()->factory()->false_value(); |
| 544 __ mov(result_register(), value); | 565 __ mov(result_register(), value); |
| 545 } | 566 } |
| 546 | 567 |
| 547 | 568 |
| 548 void FullCodeGenerator::StackValueContext::Plug(bool flag) const { | 569 void FullCodeGenerator::StackValueContext::Plug(bool flag) const { |
| 549 Handle<Object> value = flag | 570 Handle<Object> value = flag |
| 550 ? isolate()->factory()->true_value() | 571 ? isolate()->factory()->true_value() |
| 551 : isolate()->factory()->false_value(); | 572 : isolate()->factory()->false_value(); |
| 552 __ push(Immediate(value)); | 573 __ push(Immediate(value)); |
| 574 codegen()->increment_stack_height(); |
| 553 } | 575 } |
| 554 | 576 |
| 555 | 577 |
| 556 void FullCodeGenerator::TestContext::Plug(bool flag) const { | 578 void FullCodeGenerator::TestContext::Plug(bool flag) const { |
| 557 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, | 579 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, |
| 558 true, | 580 true, |
| 559 true_label_, | 581 true_label_, |
| 560 false_label_); | 582 false_label_); |
| 561 if (flag) { | 583 if (flag) { |
| 562 if (true_label_ != fall_through_) __ jmp(true_label_); | 584 if (true_label_ != fall_through_) __ jmp(true_label_); |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 715 __ push(esi); | 737 __ push(esi); |
| 716 __ push(Immediate(variable->name())); | 738 __ push(Immediate(variable->name())); |
| 717 // Declaration nodes are always introduced in one of two modes. | 739 // Declaration nodes are always introduced in one of two modes. |
| 718 ASSERT(mode == Variable::VAR || mode == Variable::CONST); | 740 ASSERT(mode == Variable::VAR || mode == Variable::CONST); |
| 719 PropertyAttributes attr = (mode == Variable::VAR) ? NONE : READ_ONLY; | 741 PropertyAttributes attr = (mode == Variable::VAR) ? NONE : READ_ONLY; |
| 720 __ push(Immediate(Smi::FromInt(attr))); | 742 __ push(Immediate(Smi::FromInt(attr))); |
| 721 // Push initial value, if any. | 743 // Push initial value, if any. |
| 722 // Note: For variables we must not push an initial value (such as | 744 // Note: For variables we must not push an initial value (such as |
| 723 // 'undefined') because we may have a (legal) redeclaration and we | 745 // 'undefined') because we may have a (legal) redeclaration and we |
| 724 // must not destroy the current value. | 746 // must not destroy the current value. |
| 747 increment_stack_height(3); |
| 725 if (mode == Variable::CONST) { | 748 if (mode == Variable::CONST) { |
| 726 __ push(Immediate(isolate()->factory()->the_hole_value())); | 749 __ push(Immediate(isolate()->factory()->the_hole_value())); |
| 750 increment_stack_height(); |
| 727 } else if (function != NULL) { | 751 } else if (function != NULL) { |
| 728 VisitForStackValue(function); | 752 VisitForStackValue(function); |
| 729 } else { | 753 } else { |
| 730 __ push(Immediate(Smi::FromInt(0))); // No initial value! | 754 __ push(Immediate(Smi::FromInt(0))); // No initial value! |
| 755 increment_stack_height(); |
| 731 } | 756 } |
| 732 __ CallRuntime(Runtime::kDeclareContextSlot, 4); | 757 __ CallRuntime(Runtime::kDeclareContextSlot, 4); |
| 758 decrement_stack_height(4); |
| 733 break; | 759 break; |
| 734 } | 760 } |
| 735 } | 761 } |
| 736 | 762 |
| 737 } else if (prop != NULL) { | 763 } else if (prop != NULL) { |
| 738 // A const declaration aliasing a parameter is an illegal redeclaration. | 764 // A const declaration aliasing a parameter is an illegal redeclaration. |
| 739 ASSERT(mode != Variable::CONST); | 765 ASSERT(mode != Variable::CONST); |
| 740 if (function != NULL) { | 766 if (function != NULL) { |
| 741 // We are declaring a function that rewrites to a property. | 767 // We are declaring a function that rewrites to a property. |
| 742 // Use (keyed) IC to set the initial value. We cannot visit the | 768 // Use (keyed) IC to set the initial value. We cannot visit the |
| 743 // rewrite because it's shared and we risk recording duplicate AST | 769 // rewrite because it's shared and we risk recording duplicate AST |
| 744 // IDs for bailouts from optimized code. | 770 // IDs for bailouts from optimized code. |
| 745 ASSERT(prop->obj()->AsVariableProxy() != NULL); | 771 ASSERT(prop->obj()->AsVariableProxy() != NULL); |
| 746 { AccumulatorValueContext for_object(this); | 772 { AccumulatorValueContext for_object(this); |
| 747 EmitVariableLoad(prop->obj()->AsVariableProxy()); | 773 EmitVariableLoad(prop->obj()->AsVariableProxy()); |
| 748 } | 774 } |
| 749 | 775 |
| 750 __ push(eax); | 776 __ push(eax); |
| 777 increment_stack_height(); |
| 751 VisitForAccumulatorValue(function); | 778 VisitForAccumulatorValue(function); |
| 752 __ pop(edx); | 779 __ pop(edx); |
| 780 decrement_stack_height(); |
| 753 | 781 |
| 754 ASSERT(prop->key()->AsLiteral() != NULL && | 782 ASSERT(prop->key()->AsLiteral() != NULL && |
| 755 prop->key()->AsLiteral()->handle()->IsSmi()); | 783 prop->key()->AsLiteral()->handle()->IsSmi()); |
| 756 __ SafeSet(ecx, Immediate(prop->key()->AsLiteral()->handle())); | 784 __ SafeSet(ecx, Immediate(prop->key()->AsLiteral()->handle())); |
| 757 | 785 |
| 758 Handle<Code> ic = is_strict_mode() | 786 Handle<Code> ic = is_strict_mode() |
| 759 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() | 787 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() |
| 760 : isolate()->builtins()->KeyedStoreIC_Initialize(); | 788 : isolate()->builtins()->KeyedStoreIC_Initialize(); |
| 761 __ call(ic); | 789 __ call(ic); |
| 762 } | 790 } |
| (...skipping 15 matching lines...) Expand all Loading... |
| 778 __ CallRuntime(Runtime::kDeclareGlobals, 4); | 806 __ CallRuntime(Runtime::kDeclareGlobals, 4); |
| 779 // Return value is ignored. | 807 // Return value is ignored. |
| 780 } | 808 } |
| 781 | 809 |
| 782 | 810 |
| 783 void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { | 811 void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { |
| 784 Comment cmnt(masm_, "[ SwitchStatement"); | 812 Comment cmnt(masm_, "[ SwitchStatement"); |
| 785 Breakable nested_statement(this, stmt); | 813 Breakable nested_statement(this, stmt); |
| 786 SetStatementPosition(stmt); | 814 SetStatementPosition(stmt); |
| 787 | 815 |
| 816 int switch_clause_stack_height = stack_height(); |
| 788 // Keep the switch value on the stack until a case matches. | 817 // Keep the switch value on the stack until a case matches. |
| 789 VisitForStackValue(stmt->tag()); | 818 VisitForStackValue(stmt->tag()); |
| 790 PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS); | 819 PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS); |
| 791 | 820 |
| 792 ZoneList<CaseClause*>* clauses = stmt->cases(); | 821 ZoneList<CaseClause*>* clauses = stmt->cases(); |
| 793 CaseClause* default_clause = NULL; // Can occur anywhere in the list. | 822 CaseClause* default_clause = NULL; // Can occur anywhere in the list. |
| 794 | 823 |
| 795 Label next_test; // Recycled for each test. | 824 Label next_test; // Recycled for each test. |
| 796 // Compile all the tests with branches to their bodies. | 825 // Compile all the tests with branches to their bodies. |
| 797 for (int i = 0; i < clauses->length(); i++) { | 826 for (int i = 0; i < clauses->length(); i++) { |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 842 // Discard the test value and jump to the default if present, otherwise to | 871 // Discard the test value and jump to the default if present, otherwise to |
| 843 // the end of the statement. | 872 // the end of the statement. |
| 844 __ bind(&next_test); | 873 __ bind(&next_test); |
| 845 __ Drop(1); // Switch value is no longer needed. | 874 __ Drop(1); // Switch value is no longer needed. |
| 846 if (default_clause == NULL) { | 875 if (default_clause == NULL) { |
| 847 __ jmp(nested_statement.break_target()); | 876 __ jmp(nested_statement.break_target()); |
| 848 } else { | 877 } else { |
| 849 __ jmp(default_clause->body_target()); | 878 __ jmp(default_clause->body_target()); |
| 850 } | 879 } |
| 851 | 880 |
| 881 set_stack_height(switch_clause_stack_height); |
| 852 // Compile all the case bodies. | 882 // Compile all the case bodies. |
| 853 for (int i = 0; i < clauses->length(); i++) { | 883 for (int i = 0; i < clauses->length(); i++) { |
| 854 Comment cmnt(masm_, "[ Case body"); | 884 Comment cmnt(masm_, "[ Case body"); |
| 855 CaseClause* clause = clauses->at(i); | 885 CaseClause* clause = clauses->at(i); |
| 856 __ bind(clause->body_target()); | 886 __ bind(clause->body_target()); |
| 857 PrepareForBailoutForId(clause->EntryId(), NO_REGISTERS); | 887 PrepareForBailoutForId(clause->EntryId(), NO_REGISTERS); |
| 858 VisitStatements(clause->statements()); | 888 VisitStatements(clause->statements()); |
| 859 } | 889 } |
| 860 | 890 |
| 861 __ bind(nested_statement.break_target()); | 891 __ bind(nested_statement.break_target()); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 883 // Convert the object to a JS object. | 913 // Convert the object to a JS object. |
| 884 Label convert, done_convert; | 914 Label convert, done_convert; |
| 885 __ JumpIfSmi(eax, &convert, Label::kNear); | 915 __ JumpIfSmi(eax, &convert, Label::kNear); |
| 886 __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx); | 916 __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx); |
| 887 __ j(above_equal, &done_convert, Label::kNear); | 917 __ j(above_equal, &done_convert, Label::kNear); |
| 888 __ bind(&convert); | 918 __ bind(&convert); |
| 889 __ push(eax); | 919 __ push(eax); |
| 890 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); | 920 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); |
| 891 __ bind(&done_convert); | 921 __ bind(&done_convert); |
| 892 __ push(eax); | 922 __ push(eax); |
| 923 increment_stack_height(); |
| 893 | 924 |
| 894 // Check cache validity in generated code. This is a fast case for | 925 // Check cache validity in generated code. This is a fast case for |
| 895 // the JSObject::IsSimpleEnum cache validity checks. If we cannot | 926 // the JSObject::IsSimpleEnum cache validity checks. If we cannot |
| 896 // guarantee cache validity, call the runtime system to check cache | 927 // guarantee cache validity, call the runtime system to check cache |
| 897 // validity or get the property names in a fixed array. | 928 // validity or get the property names in a fixed array. |
| 898 Label next, call_runtime; | 929 Label next, call_runtime; |
| 899 __ mov(ecx, eax); | 930 __ mov(ecx, eax); |
| 900 __ bind(&next); | 931 __ bind(&next); |
| 901 | 932 |
| 902 // Check that there are no elements. Register ecx contains the | 933 // Check that there are no elements. Register ecx contains the |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 966 __ jmp(&loop); | 997 __ jmp(&loop); |
| 967 | 998 |
| 968 // We got a fixed array in register eax. Iterate through that. | 999 // We got a fixed array in register eax. Iterate through that. |
| 969 __ bind(&fixed_array); | 1000 __ bind(&fixed_array); |
| 970 __ push(Immediate(Smi::FromInt(0))); // Map (0) - force slow check. | 1001 __ push(Immediate(Smi::FromInt(0))); // Map (0) - force slow check. |
| 971 __ push(eax); | 1002 __ push(eax); |
| 972 __ mov(eax, FieldOperand(eax, FixedArray::kLengthOffset)); | 1003 __ mov(eax, FieldOperand(eax, FixedArray::kLengthOffset)); |
| 973 __ push(eax); // Fixed array length (as smi). | 1004 __ push(eax); // Fixed array length (as smi). |
| 974 __ push(Immediate(Smi::FromInt(0))); // Initial index. | 1005 __ push(Immediate(Smi::FromInt(0))); // Initial index. |
| 975 | 1006 |
| 1007 increment_stack_height(4); |
| 976 // Generate code for doing the condition check. | 1008 // Generate code for doing the condition check. |
| 977 __ bind(&loop); | 1009 __ bind(&loop); |
| 978 __ mov(eax, Operand(esp, 0 * kPointerSize)); // Get the current index. | 1010 __ mov(eax, Operand(esp, 0 * kPointerSize)); // Get the current index. |
| 979 __ cmp(eax, Operand(esp, 1 * kPointerSize)); // Compare to the array length. | 1011 __ cmp(eax, Operand(esp, 1 * kPointerSize)); // Compare to the array length. |
| 980 __ j(above_equal, loop_statement.break_target()); | 1012 __ j(above_equal, loop_statement.break_target()); |
| 981 | 1013 |
| 982 // Get the current entry of the array into register ebx. | 1014 // Get the current entry of the array into register ebx. |
| 983 __ mov(ebx, Operand(esp, 2 * kPointerSize)); | 1015 __ mov(ebx, Operand(esp, 2 * kPointerSize)); |
| 984 __ mov(ebx, FieldOperand(ebx, eax, times_2, FixedArray::kHeaderSize)); | 1016 __ mov(ebx, FieldOperand(ebx, eax, times_2, FixedArray::kHeaderSize)); |
| 985 | 1017 |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1021 __ bind(loop_statement.continue_target()); | 1053 __ bind(loop_statement.continue_target()); |
| 1022 __ add(Operand(esp, 0 * kPointerSize), Immediate(Smi::FromInt(1))); | 1054 __ add(Operand(esp, 0 * kPointerSize), Immediate(Smi::FromInt(1))); |
| 1023 | 1055 |
| 1024 EmitStackCheck(stmt); | 1056 EmitStackCheck(stmt); |
| 1025 __ jmp(&loop); | 1057 __ jmp(&loop); |
| 1026 | 1058 |
| 1027 // Remove the pointers stored on the stack. | 1059 // Remove the pointers stored on the stack. |
| 1028 __ bind(loop_statement.break_target()); | 1060 __ bind(loop_statement.break_target()); |
| 1029 __ add(Operand(esp), Immediate(5 * kPointerSize)); | 1061 __ add(Operand(esp), Immediate(5 * kPointerSize)); |
| 1030 | 1062 |
| 1063 decrement_stack_height(5); |
| 1031 // Exit and decrement the loop depth. | 1064 // Exit and decrement the loop depth. |
| 1032 __ bind(&exit); | 1065 __ bind(&exit); |
| 1033 decrement_loop_depth(); | 1066 decrement_loop_depth(); |
| 1034 } | 1067 } |
| 1035 | 1068 |
| 1036 | 1069 |
| 1037 void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info, | 1070 void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info, |
| 1038 bool pretenure) { | 1071 bool pretenure) { |
| 1039 // Use the fast case closure allocation code that allocates in new | 1072 // Use the fast case closure allocation code that allocates in new |
| 1040 // space for nested functions that don't need literals cloning. If | 1073 // space for nested functions that don't need literals cloning. If |
| (...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1356 | 1389 |
| 1357 for (int i = 0; i < expr->properties()->length(); i++) { | 1390 for (int i = 0; i < expr->properties()->length(); i++) { |
| 1358 ObjectLiteral::Property* property = expr->properties()->at(i); | 1391 ObjectLiteral::Property* property = expr->properties()->at(i); |
| 1359 if (property->IsCompileTimeValue()) continue; | 1392 if (property->IsCompileTimeValue()) continue; |
| 1360 | 1393 |
| 1361 Literal* key = property->key(); | 1394 Literal* key = property->key(); |
| 1362 Expression* value = property->value(); | 1395 Expression* value = property->value(); |
| 1363 if (!result_saved) { | 1396 if (!result_saved) { |
| 1364 __ push(eax); // Save result on the stack | 1397 __ push(eax); // Save result on the stack |
| 1365 result_saved = true; | 1398 result_saved = true; |
| 1399 increment_stack_height(); |
| 1366 } | 1400 } |
| 1367 switch (property->kind()) { | 1401 switch (property->kind()) { |
| 1368 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | 1402 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
| 1369 ASSERT(!CompileTimeValue::IsCompileTimeValue(value)); | 1403 ASSERT(!CompileTimeValue::IsCompileTimeValue(value)); |
| 1370 // Fall through. | 1404 // Fall through. |
| 1371 case ObjectLiteral::Property::COMPUTED: | 1405 case ObjectLiteral::Property::COMPUTED: |
| 1372 if (key->handle()->IsSymbol()) { | 1406 if (key->handle()->IsSymbol()) { |
| 1373 if (property->emit_store()) { | 1407 if (property->emit_store()) { |
| 1374 VisitForAccumulatorValue(value); | 1408 VisitForAccumulatorValue(value); |
| 1375 __ mov(ecx, Immediate(key->handle())); | 1409 __ mov(ecx, Immediate(key->handle())); |
| 1376 __ mov(edx, Operand(esp, 0)); | 1410 __ mov(edx, Operand(esp, 0)); |
| 1377 Handle<Code> ic = is_strict_mode() | 1411 Handle<Code> ic = is_strict_mode() |
| 1378 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 1412 ? isolate()->builtins()->StoreIC_Initialize_Strict() |
| 1379 : isolate()->builtins()->StoreIC_Initialize(); | 1413 : isolate()->builtins()->StoreIC_Initialize(); |
| 1380 __ call(ic, RelocInfo::CODE_TARGET, key->id()); | 1414 __ call(ic, RelocInfo::CODE_TARGET, key->id()); |
| 1381 PrepareForBailoutForId(key->id(), NO_REGISTERS); | 1415 PrepareForBailoutForId(key->id(), NO_REGISTERS); |
| 1382 } else { | 1416 } else { |
| 1383 VisitForEffect(value); | 1417 VisitForEffect(value); |
| 1384 } | 1418 } |
| 1385 break; | 1419 break; |
| 1386 } | 1420 } |
| 1387 // Fall through. | 1421 // Fall through. |
| 1388 case ObjectLiteral::Property::PROTOTYPE: | 1422 case ObjectLiteral::Property::PROTOTYPE: |
| 1389 __ push(Operand(esp, 0)); // Duplicate receiver. | 1423 __ push(Operand(esp, 0)); // Duplicate receiver. |
| 1424 increment_stack_height(); |
| 1390 VisitForStackValue(key); | 1425 VisitForStackValue(key); |
| 1391 VisitForStackValue(value); | 1426 VisitForStackValue(value); |
| 1392 if (property->emit_store()) { | 1427 if (property->emit_store()) { |
| 1393 __ push(Immediate(Smi::FromInt(NONE))); // PropertyAttributes | 1428 __ push(Immediate(Smi::FromInt(NONE))); // PropertyAttributes |
| 1394 __ CallRuntime(Runtime::kSetProperty, 4); | 1429 __ CallRuntime(Runtime::kSetProperty, 4); |
| 1395 } else { | 1430 } else { |
| 1396 __ Drop(3); | 1431 __ Drop(3); |
| 1397 } | 1432 } |
| 1433 decrement_stack_height(3); |
| 1398 break; | 1434 break; |
| 1399 case ObjectLiteral::Property::SETTER: | 1435 case ObjectLiteral::Property::SETTER: |
| 1400 case ObjectLiteral::Property::GETTER: | 1436 case ObjectLiteral::Property::GETTER: |
| 1401 __ push(Operand(esp, 0)); // Duplicate receiver. | 1437 __ push(Operand(esp, 0)); // Duplicate receiver. |
| 1438 increment_stack_height(); |
| 1402 VisitForStackValue(key); | 1439 VisitForStackValue(key); |
| 1403 __ push(Immediate(property->kind() == ObjectLiteral::Property::SETTER ? | 1440 __ push(Immediate(property->kind() == ObjectLiteral::Property::SETTER ? |
| 1404 Smi::FromInt(1) : | 1441 Smi::FromInt(1) : |
| 1405 Smi::FromInt(0))); | 1442 Smi::FromInt(0))); |
| 1443 increment_stack_height(); |
| 1406 VisitForStackValue(value); | 1444 VisitForStackValue(value); |
| 1407 __ CallRuntime(Runtime::kDefineAccessor, 4); | 1445 __ CallRuntime(Runtime::kDefineAccessor, 4); |
| 1446 decrement_stack_height(4); |
| 1408 break; | 1447 break; |
| 1409 default: UNREACHABLE(); | 1448 default: UNREACHABLE(); |
| 1410 } | 1449 } |
| 1411 } | 1450 } |
| 1412 | 1451 |
| 1413 if (expr->has_function()) { | 1452 if (expr->has_function()) { |
| 1414 ASSERT(result_saved); | 1453 ASSERT(result_saved); |
| 1415 __ push(Operand(esp, 0)); | 1454 __ push(Operand(esp, 0)); |
| 1416 __ CallRuntime(Runtime::kToFastProperties, 1); | 1455 __ CallRuntime(Runtime::kToFastProperties, 1); |
| 1417 } | 1456 } |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1460 // If the subexpression is a literal or a simple materialized literal it | 1499 // If the subexpression is a literal or a simple materialized literal it |
| 1461 // is already set in the cloned array. | 1500 // is already set in the cloned array. |
| 1462 if (subexpr->AsLiteral() != NULL || | 1501 if (subexpr->AsLiteral() != NULL || |
| 1463 CompileTimeValue::IsCompileTimeValue(subexpr)) { | 1502 CompileTimeValue::IsCompileTimeValue(subexpr)) { |
| 1464 continue; | 1503 continue; |
| 1465 } | 1504 } |
| 1466 | 1505 |
| 1467 if (!result_saved) { | 1506 if (!result_saved) { |
| 1468 __ push(eax); | 1507 __ push(eax); |
| 1469 result_saved = true; | 1508 result_saved = true; |
| 1509 increment_stack_height(); |
| 1470 } | 1510 } |
| 1471 VisitForAccumulatorValue(subexpr); | 1511 VisitForAccumulatorValue(subexpr); |
| 1472 | 1512 |
| 1473 // Store the subexpression value in the array's elements. | 1513 // Store the subexpression value in the array's elements. |
| 1474 __ mov(ebx, Operand(esp, 0)); // Copy of array literal. | 1514 __ mov(ebx, Operand(esp, 0)); // Copy of array literal. |
| 1475 __ mov(ebx, FieldOperand(ebx, JSObject::kElementsOffset)); | 1515 __ mov(ebx, FieldOperand(ebx, JSObject::kElementsOffset)); |
| 1476 int offset = FixedArray::kHeaderSize + (i * kPointerSize); | 1516 int offset = FixedArray::kHeaderSize + (i * kPointerSize); |
| 1477 __ mov(FieldOperand(ebx, offset), result_register()); | 1517 __ mov(FieldOperand(ebx, offset), result_register()); |
| 1478 | 1518 |
| 1479 // Update the write barrier for the array store. | 1519 // Update the write barrier for the array store. |
| 1480 __ RecordWrite(ebx, offset, result_register(), ecx); | 1520 __ RecordWrite(ebx, offset, result_register(), ecx); |
| 1481 | 1521 |
| 1482 PrepareForBailoutForId(expr->GetIdForElement(i), NO_REGISTERS); | 1522 PrepareForBailoutForId(expr->GetIdForElement(i), NO_REGISTERS); |
| 1483 } | 1523 } |
| 1484 | 1524 |
| 1485 if (result_saved) { | 1525 if (result_saved) { |
| 1486 context()->PlugTOS(); | 1526 context()->PlugTOS(); |
| 1487 } else { | 1527 } else { |
| 1488 context()->Plug(eax); | 1528 context()->Plug(eax); |
| 1489 } | 1529 } |
| 1490 } | 1530 } |
| 1491 | 1531 |
| 1492 | 1532 |
| 1493 void FullCodeGenerator::VisitAssignment(Assignment* expr) { | 1533 void FullCodeGenerator::VisitAssignment(Assignment* expr) { |
| 1494 Comment cmnt(masm_, "[ Assignment"); | 1534 Comment cmnt(masm_, "[ Assignment"); |
| 1495 // Invalid left-hand sides are rewritten to have a 'throw ReferenceError' | 1535 // Invalid left-hand sides are rewritten to have a 'throw ReferenceError' |
| 1496 // on the left-hand side. | 1536 // on the left-hand side. |
| 1497 if (!expr->target()->IsValidLeftHandSide()) { | 1537 if (!expr->target()->IsValidLeftHandSide()) { |
| 1498 VisitForEffect(expr->target()); | 1538 ASSERT(expr->target()->AsThrow() != NULL); |
| 1539 VisitInCurrentContext(expr->target()); // Throw does not plug the context |
| 1540 context()->Plug(eax); |
| 1499 return; | 1541 return; |
| 1500 } | 1542 } |
| 1501 | 1543 |
| 1502 // Left-hand side can only be a property, a global or a (parameter or local) | 1544 // Left-hand side can only be a property, a global or a (parameter or local) |
| 1503 // slot. | 1545 // slot. |
| 1504 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; | 1546 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; |
| 1505 LhsKind assign_type = VARIABLE; | 1547 LhsKind assign_type = VARIABLE; |
| 1506 Property* property = expr->target()->AsProperty(); | 1548 Property* property = expr->target()->AsProperty(); |
| 1507 if (property != NULL) { | 1549 if (property != NULL) { |
| 1508 assign_type = (property->key()->IsPropertyName()) | 1550 assign_type = (property->key()->IsPropertyName()) |
| 1509 ? NAMED_PROPERTY | 1551 ? NAMED_PROPERTY |
| 1510 : KEYED_PROPERTY; | 1552 : KEYED_PROPERTY; |
| 1511 } | 1553 } |
| 1512 | 1554 |
| 1513 // Evaluate LHS expression. | 1555 // Evaluate LHS expression. |
| 1514 switch (assign_type) { | 1556 switch (assign_type) { |
| 1515 case VARIABLE: | 1557 case VARIABLE: |
| 1516 // Nothing to do here. | 1558 // Nothing to do here. |
| 1517 break; | 1559 break; |
| 1518 case NAMED_PROPERTY: | 1560 case NAMED_PROPERTY: |
| 1519 if (expr->is_compound()) { | 1561 if (expr->is_compound()) { |
| 1520 // We need the receiver both on the stack and in the accumulator. | 1562 // We need the receiver both on the stack and in the accumulator. |
| 1521 VisitForAccumulatorValue(property->obj()); | 1563 VisitForAccumulatorValue(property->obj()); |
| 1522 __ push(result_register()); | 1564 __ push(result_register()); |
| 1565 increment_stack_height(); |
| 1523 } else { | 1566 } else { |
| 1524 VisitForStackValue(property->obj()); | 1567 VisitForStackValue(property->obj()); |
| 1525 } | 1568 } |
| 1526 break; | 1569 break; |
| 1527 case KEYED_PROPERTY: { | 1570 case KEYED_PROPERTY: { |
| 1528 if (expr->is_compound()) { | 1571 if (expr->is_compound()) { |
| 1529 VisitForStackValue(property->obj()); | 1572 VisitForStackValue(property->obj()); |
| 1530 VisitForAccumulatorValue(property->key()); | 1573 VisitForAccumulatorValue(property->key()); |
| 1531 __ mov(edx, Operand(esp, 0)); | 1574 __ mov(edx, Operand(esp, 0)); |
| 1532 __ push(eax); | 1575 __ push(eax); |
| 1576 increment_stack_height(); |
| 1533 } else { | 1577 } else { |
| 1534 VisitForStackValue(property->obj()); | 1578 VisitForStackValue(property->obj()); |
| 1535 VisitForStackValue(property->key()); | 1579 VisitForStackValue(property->key()); |
| 1536 } | 1580 } |
| 1537 break; | 1581 break; |
| 1538 } | 1582 } |
| 1539 } | 1583 } |
| 1540 | 1584 |
| 1541 // For compound assignments we need another deoptimization point after the | 1585 // For compound assignments we need another deoptimization point after the |
| 1542 // variable/property load. | 1586 // variable/property load. |
| 1543 if (expr->is_compound()) { | 1587 if (expr->is_compound()) { |
| 1544 { AccumulatorValueContext context(this); | 1588 AccumulatorValueContext result_context(this); |
| 1589 { AccumulatorValueContext left_operand_context(this); |
| 1545 switch (assign_type) { | 1590 switch (assign_type) { |
| 1546 case VARIABLE: | 1591 case VARIABLE: |
| 1547 EmitVariableLoad(expr->target()->AsVariableProxy()); | 1592 EmitVariableLoad(expr->target()->AsVariableProxy()); |
| 1548 PrepareForBailout(expr->target(), TOS_REG); | 1593 PrepareForBailout(expr->target(), TOS_REG); |
| 1549 break; | 1594 break; |
| 1550 case NAMED_PROPERTY: | 1595 case NAMED_PROPERTY: |
| 1551 EmitNamedPropertyLoad(property); | 1596 EmitNamedPropertyLoad(property); |
| 1552 PrepareForBailoutForId(expr->CompoundLoadId(), TOS_REG); | 1597 PrepareForBailoutForId(expr->CompoundLoadId(), TOS_REG); |
| 1553 break; | 1598 break; |
| 1554 case KEYED_PROPERTY: | 1599 case KEYED_PROPERTY: |
| 1555 EmitKeyedPropertyLoad(property); | 1600 EmitKeyedPropertyLoad(property); |
| 1556 PrepareForBailoutForId(expr->CompoundLoadId(), TOS_REG); | 1601 PrepareForBailoutForId(expr->CompoundLoadId(), TOS_REG); |
| 1557 break; | 1602 break; |
| 1558 } | 1603 } |
| 1559 } | 1604 } |
| 1560 | 1605 |
| 1561 Token::Value op = expr->binary_op(); | 1606 Token::Value op = expr->binary_op(); |
| 1562 __ push(eax); // Left operand goes on the stack. | 1607 __ push(eax); // Left operand goes on the stack. |
| 1608 increment_stack_height(); |
| 1563 VisitForAccumulatorValue(expr->value()); | 1609 VisitForAccumulatorValue(expr->value()); |
| 1564 | 1610 |
| 1565 OverwriteMode mode = expr->value()->ResultOverwriteAllowed() | 1611 OverwriteMode mode = expr->value()->ResultOverwriteAllowed() |
| 1566 ? OVERWRITE_RIGHT | 1612 ? OVERWRITE_RIGHT |
| 1567 : NO_OVERWRITE; | 1613 : NO_OVERWRITE; |
| 1568 SetSourcePosition(expr->position() + 1); | 1614 SetSourcePosition(expr->position() + 1); |
| 1569 AccumulatorValueContext context(this); | |
| 1570 if (ShouldInlineSmiCase(op)) { | 1615 if (ShouldInlineSmiCase(op)) { |
| 1571 EmitInlineSmiBinaryOp(expr->binary_operation(), | 1616 EmitInlineSmiBinaryOp(expr->binary_operation(), |
| 1572 op, | 1617 op, |
| 1573 mode, | 1618 mode, |
| 1574 expr->target(), | 1619 expr->target(), |
| 1575 expr->value()); | 1620 expr->value()); |
| 1576 } else { | 1621 } else { |
| 1577 EmitBinaryOp(expr->binary_operation(), op, mode); | 1622 EmitBinaryOp(expr->binary_operation(), op, mode); |
| 1578 } | 1623 } |
| 1579 | 1624 |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1623 | 1668 |
| 1624 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, | 1669 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, |
| 1625 Token::Value op, | 1670 Token::Value op, |
| 1626 OverwriteMode mode, | 1671 OverwriteMode mode, |
| 1627 Expression* left, | 1672 Expression* left, |
| 1628 Expression* right) { | 1673 Expression* right) { |
| 1629 // Do combined smi check of the operands. Left operand is on the | 1674 // Do combined smi check of the operands. Left operand is on the |
| 1630 // stack. Right operand is in eax. | 1675 // stack. Right operand is in eax. |
| 1631 Label smi_case, done, stub_call; | 1676 Label smi_case, done, stub_call; |
| 1632 __ pop(edx); | 1677 __ pop(edx); |
| 1678 decrement_stack_height(); |
| 1633 __ mov(ecx, eax); | 1679 __ mov(ecx, eax); |
| 1634 __ or_(eax, Operand(edx)); | 1680 __ or_(eax, Operand(edx)); |
| 1635 JumpPatchSite patch_site(masm_); | 1681 JumpPatchSite patch_site(masm_); |
| 1636 patch_site.EmitJumpIfSmi(eax, &smi_case, Label::kNear); | 1682 patch_site.EmitJumpIfSmi(eax, &smi_case, Label::kNear); |
| 1637 | 1683 |
| 1638 __ bind(&stub_call); | 1684 __ bind(&stub_call); |
| 1639 __ mov(eax, ecx); | 1685 __ mov(eax, ecx); |
| 1640 BinaryOpStub stub(op, mode); | 1686 BinaryOpStub stub(op, mode); |
| 1641 __ call(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id()); | 1687 __ call(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id()); |
| 1642 patch_site.EmitPatchInfo(); | 1688 patch_site.EmitPatchInfo(); |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1714 | 1760 |
| 1715 __ bind(&done); | 1761 __ bind(&done); |
| 1716 context()->Plug(eax); | 1762 context()->Plug(eax); |
| 1717 } | 1763 } |
| 1718 | 1764 |
| 1719 | 1765 |
| 1720 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, | 1766 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, |
| 1721 Token::Value op, | 1767 Token::Value op, |
| 1722 OverwriteMode mode) { | 1768 OverwriteMode mode) { |
| 1723 __ pop(edx); | 1769 __ pop(edx); |
| 1770 decrement_stack_height(); |
| 1724 BinaryOpStub stub(op, mode); | 1771 BinaryOpStub stub(op, mode); |
| 1725 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. | 1772 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. |
| 1726 __ call(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id()); | 1773 __ call(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id()); |
| 1727 patch_site.EmitPatchInfo(); | 1774 patch_site.EmitPatchInfo(); |
| 1728 context()->Plug(eax); | 1775 context()->Plug(eax); |
| 1729 } | 1776 } |
| 1730 | 1777 |
| 1731 | 1778 |
| 1732 void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) { | 1779 void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) { |
| 1733 // Invalid left-hand sides are rewritten to have a 'throw | 1780 // Invalid left-hand sides are rewritten to have a 'throw |
| 1734 // ReferenceError' on the left-hand side. | 1781 // ReferenceError' on the left-hand side. |
| 1735 if (!expr->IsValidLeftHandSide()) { | 1782 if (!expr->IsValidLeftHandSide()) { |
| 1736 VisitForEffect(expr); | 1783 ASSERT(expr->AsThrow() != NULL); |
| 1784 VisitInCurrentContext(expr); // Throw does not plug the context |
| 1785 context()->Plug(eax); |
| 1737 return; | 1786 return; |
| 1738 } | 1787 } |
| 1739 | 1788 |
| 1740 // Left-hand side can only be a property, a global or a (parameter or local) | 1789 // Left-hand side can only be a property, a global or a (parameter or local) |
| 1741 // slot. | 1790 // slot. |
| 1742 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; | 1791 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; |
| 1743 LhsKind assign_type = VARIABLE; | 1792 LhsKind assign_type = VARIABLE; |
| 1744 Property* prop = expr->AsProperty(); | 1793 Property* prop = expr->AsProperty(); |
| 1745 if (prop != NULL) { | 1794 if (prop != NULL) { |
| 1746 assign_type = (prop->key()->IsPropertyName()) | 1795 assign_type = (prop->key()->IsPropertyName()) |
| 1747 ? NAMED_PROPERTY | 1796 ? NAMED_PROPERTY |
| 1748 : KEYED_PROPERTY; | 1797 : KEYED_PROPERTY; |
| 1749 } | 1798 } |
| 1750 | 1799 |
| 1751 switch (assign_type) { | 1800 switch (assign_type) { |
| 1752 case VARIABLE: { | 1801 case VARIABLE: { |
| 1753 Variable* var = expr->AsVariableProxy()->var(); | 1802 Variable* var = expr->AsVariableProxy()->var(); |
| 1754 EffectContext context(this); | 1803 EffectContext context(this); |
| 1755 EmitVariableAssignment(var, Token::ASSIGN); | 1804 EmitVariableAssignment(var, Token::ASSIGN); |
| 1756 break; | 1805 break; |
| 1757 } | 1806 } |
| 1758 case NAMED_PROPERTY: { | 1807 case NAMED_PROPERTY: { |
| 1759 __ push(eax); // Preserve value. | 1808 __ push(eax); // Preserve value. |
| 1809 increment_stack_height(); |
| 1760 VisitForAccumulatorValue(prop->obj()); | 1810 VisitForAccumulatorValue(prop->obj()); |
| 1761 __ mov(edx, eax); | 1811 __ mov(edx, eax); |
| 1762 __ pop(eax); // Restore value. | 1812 __ pop(eax); // Restore value. |
| 1813 decrement_stack_height(); |
| 1763 __ mov(ecx, prop->key()->AsLiteral()->handle()); | 1814 __ mov(ecx, prop->key()->AsLiteral()->handle()); |
| 1764 Handle<Code> ic = is_strict_mode() | 1815 Handle<Code> ic = is_strict_mode() |
| 1765 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 1816 ? isolate()->builtins()->StoreIC_Initialize_Strict() |
| 1766 : isolate()->builtins()->StoreIC_Initialize(); | 1817 : isolate()->builtins()->StoreIC_Initialize(); |
| 1767 __ call(ic); | 1818 __ call(ic); |
| 1768 break; | 1819 break; |
| 1769 } | 1820 } |
| 1770 case KEYED_PROPERTY: { | 1821 case KEYED_PROPERTY: { |
| 1771 __ push(eax); // Preserve value. | 1822 __ push(eax); // Preserve value. |
| 1823 increment_stack_height(); |
| 1772 if (prop->is_synthetic()) { | 1824 if (prop->is_synthetic()) { |
| 1773 ASSERT(prop->obj()->AsVariableProxy() != NULL); | 1825 ASSERT(prop->obj()->AsVariableProxy() != NULL); |
| 1774 ASSERT(prop->key()->AsLiteral() != NULL); | 1826 ASSERT(prop->key()->AsLiteral() != NULL); |
| 1775 { AccumulatorValueContext for_object(this); | 1827 { AccumulatorValueContext for_object(this); |
| 1776 EmitVariableLoad(prop->obj()->AsVariableProxy()); | 1828 EmitVariableLoad(prop->obj()->AsVariableProxy()); |
| 1777 } | 1829 } |
| 1778 __ mov(edx, eax); | 1830 __ mov(edx, eax); |
| 1779 __ SafeSet(ecx, Immediate(prop->key()->AsLiteral()->handle())); | 1831 __ SafeSet(ecx, Immediate(prop->key()->AsLiteral()->handle())); |
| 1780 } else { | 1832 } else { |
| 1781 VisitForStackValue(prop->obj()); | 1833 VisitForStackValue(prop->obj()); |
| 1782 VisitForAccumulatorValue(prop->key()); | 1834 VisitForAccumulatorValue(prop->key()); |
| 1783 __ mov(ecx, eax); | 1835 __ mov(ecx, eax); |
| 1784 __ pop(edx); | 1836 __ pop(edx); |
| 1837 decrement_stack_height(); |
| 1785 } | 1838 } |
| 1786 __ pop(eax); // Restore value. | 1839 __ pop(eax); // Restore value. |
| 1840 decrement_stack_height(); |
| 1787 Handle<Code> ic = is_strict_mode() | 1841 Handle<Code> ic = is_strict_mode() |
| 1788 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() | 1842 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() |
| 1789 : isolate()->builtins()->KeyedStoreIC_Initialize(); | 1843 : isolate()->builtins()->KeyedStoreIC_Initialize(); |
| 1790 __ call(ic); | 1844 __ call(ic); |
| 1791 break; | 1845 break; |
| 1792 } | 1846 } |
| 1793 } | 1847 } |
| 1794 PrepareForBailoutForId(bailout_ast_id, TOS_REG); | 1848 PrepareForBailoutForId(bailout_ast_id, TOS_REG); |
| 1795 context()->Plug(eax); | 1849 context()->Plug(eax); |
| 1796 } | 1850 } |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1893 __ pop(result_register()); | 1947 __ pop(result_register()); |
| 1894 } | 1948 } |
| 1895 | 1949 |
| 1896 // Record source code position before IC call. | 1950 // Record source code position before IC call. |
| 1897 SetSourcePosition(expr->position()); | 1951 SetSourcePosition(expr->position()); |
| 1898 __ mov(ecx, prop->key()->AsLiteral()->handle()); | 1952 __ mov(ecx, prop->key()->AsLiteral()->handle()); |
| 1899 if (expr->ends_initialization_block()) { | 1953 if (expr->ends_initialization_block()) { |
| 1900 __ mov(edx, Operand(esp, 0)); | 1954 __ mov(edx, Operand(esp, 0)); |
| 1901 } else { | 1955 } else { |
| 1902 __ pop(edx); | 1956 __ pop(edx); |
| 1957 decrement_stack_height(); |
| 1903 } | 1958 } |
| 1904 Handle<Code> ic = is_strict_mode() | 1959 Handle<Code> ic = is_strict_mode() |
| 1905 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 1960 ? isolate()->builtins()->StoreIC_Initialize_Strict() |
| 1906 : isolate()->builtins()->StoreIC_Initialize(); | 1961 : isolate()->builtins()->StoreIC_Initialize(); |
| 1907 __ call(ic, RelocInfo::CODE_TARGET, expr->id()); | 1962 __ call(ic, RelocInfo::CODE_TARGET, expr->id()); |
| 1908 | 1963 |
| 1909 // If the assignment ends an initialization block, revert to fast case. | 1964 // If the assignment ends an initialization block, revert to fast case. |
| 1910 if (expr->ends_initialization_block()) { | 1965 if (expr->ends_initialization_block()) { |
| 1911 __ push(eax); // Result of assignment, saved even if not needed. | 1966 __ push(eax); // Result of assignment, saved even if not needed. |
| 1912 __ push(Operand(esp, kPointerSize)); // Receiver is under value. | 1967 __ push(Operand(esp, kPointerSize)); // Receiver is under value. |
| 1913 __ CallRuntime(Runtime::kToFastProperties, 1); | 1968 __ CallRuntime(Runtime::kToFastProperties, 1); |
| 1914 __ pop(eax); | 1969 __ pop(eax); |
| 1915 __ Drop(1); | 1970 __ Drop(1); |
| 1971 decrement_stack_height(); |
| 1916 } | 1972 } |
| 1917 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 1973 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 1918 context()->Plug(eax); | 1974 context()->Plug(eax); |
| 1919 } | 1975 } |
| 1920 | 1976 |
| 1921 | 1977 |
| 1922 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { | 1978 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { |
| 1923 // Assignment to a property, using a keyed store IC. | 1979 // Assignment to a property, using a keyed store IC. |
| 1924 | 1980 |
| 1925 // If the assignment starts a block of assignments to the same object, | 1981 // If the assignment starts a block of assignments to the same object, |
| 1926 // change to slow case to avoid the quadratic behavior of repeatedly | 1982 // change to slow case to avoid the quadratic behavior of repeatedly |
| 1927 // adding fast properties. | 1983 // adding fast properties. |
| 1928 if (expr->starts_initialization_block()) { | 1984 if (expr->starts_initialization_block()) { |
| 1929 __ push(result_register()); | 1985 __ push(result_register()); |
| 1930 // Receiver is now under the key and value. | 1986 // Receiver is now under the key and value. |
| 1931 __ push(Operand(esp, 2 * kPointerSize)); | 1987 __ push(Operand(esp, 2 * kPointerSize)); |
| 1932 __ CallRuntime(Runtime::kToSlowProperties, 1); | 1988 __ CallRuntime(Runtime::kToSlowProperties, 1); |
| 1933 __ pop(result_register()); | 1989 __ pop(result_register()); |
| 1934 } | 1990 } |
| 1935 | 1991 |
| 1936 __ pop(ecx); | 1992 __ pop(ecx); |
| 1993 decrement_stack_height(); |
| 1937 if (expr->ends_initialization_block()) { | 1994 if (expr->ends_initialization_block()) { |
| 1938 __ mov(edx, Operand(esp, 0)); // Leave receiver on the stack for later. | 1995 __ mov(edx, Operand(esp, 0)); // Leave receiver on the stack for later. |
| 1939 } else { | 1996 } else { |
| 1940 __ pop(edx); | 1997 __ pop(edx); |
| 1998 decrement_stack_height(); |
| 1941 } | 1999 } |
| 1942 // Record source code position before IC call. | 2000 // Record source code position before IC call. |
| 1943 SetSourcePosition(expr->position()); | 2001 SetSourcePosition(expr->position()); |
| 1944 Handle<Code> ic = is_strict_mode() | 2002 Handle<Code> ic = is_strict_mode() |
| 1945 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() | 2003 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() |
| 1946 : isolate()->builtins()->KeyedStoreIC_Initialize(); | 2004 : isolate()->builtins()->KeyedStoreIC_Initialize(); |
| 1947 __ call(ic, RelocInfo::CODE_TARGET, expr->id()); | 2005 __ call(ic, RelocInfo::CODE_TARGET, expr->id()); |
| 1948 | 2006 |
| 1949 // If the assignment ends an initialization block, revert to fast case. | 2007 // If the assignment ends an initialization block, revert to fast case. |
| 1950 if (expr->ends_initialization_block()) { | 2008 if (expr->ends_initialization_block()) { |
| 1951 __ pop(edx); | 2009 __ pop(edx); |
| 1952 __ push(eax); // Result of assignment, saved even if not needed. | 2010 __ push(eax); // Result of assignment, saved even if not needed. |
| 1953 __ push(edx); | 2011 __ push(edx); |
| 1954 __ CallRuntime(Runtime::kToFastProperties, 1); | 2012 __ CallRuntime(Runtime::kToFastProperties, 1); |
| 1955 __ pop(eax); | 2013 __ pop(eax); |
| 2014 decrement_stack_height(); |
| 1956 } | 2015 } |
| 1957 | 2016 |
| 1958 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 2017 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 1959 context()->Plug(eax); | 2018 context()->Plug(eax); |
| 1960 } | 2019 } |
| 1961 | 2020 |
| 1962 | 2021 |
| 1963 void FullCodeGenerator::VisitProperty(Property* expr) { | 2022 void FullCodeGenerator::VisitProperty(Property* expr) { |
| 1964 Comment cmnt(masm_, "[ Property"); | 2023 Comment cmnt(masm_, "[ Property"); |
| 1965 Expression* key = expr->key(); | 2024 Expression* key = expr->key(); |
| 1966 | 2025 |
| 1967 if (key->IsPropertyName()) { | 2026 if (key->IsPropertyName()) { |
| 1968 VisitForAccumulatorValue(expr->obj()); | 2027 VisitForAccumulatorValue(expr->obj()); |
| 1969 EmitNamedPropertyLoad(expr); | 2028 EmitNamedPropertyLoad(expr); |
| 1970 context()->Plug(eax); | 2029 context()->Plug(eax); |
| 1971 } else { | 2030 } else { |
| 1972 VisitForStackValue(expr->obj()); | 2031 VisitForStackValue(expr->obj()); |
| 1973 VisitForAccumulatorValue(expr->key()); | 2032 VisitForAccumulatorValue(expr->key()); |
| 1974 __ pop(edx); | 2033 __ pop(edx); |
| 2034 decrement_stack_height(); |
| 1975 EmitKeyedPropertyLoad(expr); | 2035 EmitKeyedPropertyLoad(expr); |
| 1976 context()->Plug(eax); | 2036 context()->Plug(eax); |
| 1977 } | 2037 } |
| 1978 } | 2038 } |
| 1979 | 2039 |
| 1980 | 2040 |
| 1981 void FullCodeGenerator::EmitCallWithIC(Call* expr, | 2041 void FullCodeGenerator::EmitCallWithIC(Call* expr, |
| 1982 Handle<Object> name, | 2042 Handle<Object> name, |
| 1983 RelocInfo::Mode mode) { | 2043 RelocInfo::Mode mode) { |
| 1984 // Code common for calls using the IC. | 2044 // Code common for calls using the IC. |
| 1985 ZoneList<Expression*>* args = expr->arguments(); | 2045 ZoneList<Expression*>* args = expr->arguments(); |
| 1986 int arg_count = args->length(); | 2046 int arg_count = args->length(); |
| 1987 { PreservePositionScope scope(masm()->positions_recorder()); | 2047 { PreservePositionScope scope(masm()->positions_recorder()); |
| 1988 for (int i = 0; i < arg_count; i++) { | 2048 for (int i = 0; i < arg_count; i++) { |
| 1989 VisitForStackValue(args->at(i)); | 2049 VisitForStackValue(args->at(i)); |
| 1990 } | 2050 } |
| 1991 __ Set(ecx, Immediate(name)); | 2051 __ Set(ecx, Immediate(name)); |
| 1992 } | 2052 } |
| 1993 // Record source position of the IC call. | 2053 // Record source position of the IC call. |
| 1994 SetSourcePosition(expr->position()); | 2054 SetSourcePosition(expr->position()); |
| 1995 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; | 2055 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; |
| 1996 Handle<Code> ic = | 2056 Handle<Code> ic = |
| 1997 isolate()->stub_cache()->ComputeCallInitialize(arg_count, in_loop, mode); | 2057 isolate()->stub_cache()->ComputeCallInitialize(arg_count, in_loop, mode); |
| 1998 __ call(ic, mode, expr->id()); | 2058 __ call(ic, mode, expr->id()); |
| 1999 RecordJSReturnSite(expr); | 2059 RecordJSReturnSite(expr); |
| 2000 // Restore context register. | 2060 // Restore context register. |
| 2001 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 2061 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 2062 decrement_stack_height(arg_count + 1); |
| 2002 context()->Plug(eax); | 2063 context()->Plug(eax); |
| 2003 } | 2064 } |
| 2004 | 2065 |
| 2005 | 2066 |
| 2006 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, | 2067 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, |
| 2007 Expression* key) { | 2068 Expression* key) { |
| 2008 // Load the key. | 2069 // Load the key. |
| 2009 VisitForAccumulatorValue(key); | 2070 VisitForAccumulatorValue(key); |
| 2010 | 2071 |
| 2011 // Swap the name of the function and the receiver on the stack to follow | 2072 // Swap the name of the function and the receiver on the stack to follow |
| 2012 // the calling convention for call ICs. | 2073 // the calling convention for call ICs. |
| 2013 __ pop(ecx); | 2074 __ pop(ecx); |
| 2014 __ push(eax); | 2075 __ push(eax); |
| 2015 __ push(ecx); | 2076 __ push(ecx); |
| 2077 increment_stack_height(); |
| 2016 | 2078 |
| 2017 // Load the arguments. | 2079 // Load the arguments. |
| 2018 ZoneList<Expression*>* args = expr->arguments(); | 2080 ZoneList<Expression*>* args = expr->arguments(); |
| 2019 int arg_count = args->length(); | 2081 int arg_count = args->length(); |
| 2020 { PreservePositionScope scope(masm()->positions_recorder()); | 2082 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2021 for (int i = 0; i < arg_count; i++) { | 2083 for (int i = 0; i < arg_count; i++) { |
| 2022 VisitForStackValue(args->at(i)); | 2084 VisitForStackValue(args->at(i)); |
| 2023 } | 2085 } |
| 2024 } | 2086 } |
| 2025 // Record source position of the IC call. | 2087 // Record source position of the IC call. |
| 2026 SetSourcePosition(expr->position()); | 2088 SetSourcePosition(expr->position()); |
| 2027 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; | 2089 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; |
| 2028 Handle<Code> ic = isolate()->stub_cache()->ComputeKeyedCallInitialize( | 2090 Handle<Code> ic = isolate()->stub_cache()->ComputeKeyedCallInitialize( |
| 2029 arg_count, in_loop); | 2091 arg_count, in_loop); |
| 2030 __ mov(ecx, Operand(esp, (arg_count + 1) * kPointerSize)); // Key. | 2092 __ mov(ecx, Operand(esp, (arg_count + 1) * kPointerSize)); // Key. |
| 2031 __ call(ic, RelocInfo::CODE_TARGET, expr->id()); | 2093 __ call(ic, RelocInfo::CODE_TARGET, expr->id()); |
| 2032 RecordJSReturnSite(expr); | 2094 RecordJSReturnSite(expr); |
| 2033 // Restore context register. | 2095 // Restore context register. |
| 2034 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 2096 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 2097 decrement_stack_height(arg_count + 1); |
| 2035 context()->DropAndPlug(1, eax); // Drop the key still on the stack. | 2098 context()->DropAndPlug(1, eax); // Drop the key still on the stack. |
| 2036 } | 2099 } |
| 2037 | 2100 |
| 2038 | 2101 |
| 2039 void FullCodeGenerator::EmitCallWithStub(Call* expr, CallFunctionFlags flags) { | 2102 void FullCodeGenerator::EmitCallWithStub(Call* expr, CallFunctionFlags flags) { |
| 2040 // Code common for calls using the call stub. | 2103 // Code common for calls using the call stub. |
| 2041 ZoneList<Expression*>* args = expr->arguments(); | 2104 ZoneList<Expression*>* args = expr->arguments(); |
| 2042 int arg_count = args->length(); | 2105 int arg_count = args->length(); |
| 2043 { PreservePositionScope scope(masm()->positions_recorder()); | 2106 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2044 for (int i = 0; i < arg_count; i++) { | 2107 for (int i = 0; i < arg_count; i++) { |
| 2045 VisitForStackValue(args->at(i)); | 2108 VisitForStackValue(args->at(i)); |
| 2046 } | 2109 } |
| 2047 } | 2110 } |
| 2048 // Record source position for debugger. | 2111 // Record source position for debugger. |
| 2049 SetSourcePosition(expr->position()); | 2112 SetSourcePosition(expr->position()); |
| 2050 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; | 2113 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; |
| 2051 CallFunctionStub stub(arg_count, in_loop, flags); | 2114 CallFunctionStub stub(arg_count, in_loop, flags); |
| 2052 __ CallStub(&stub); | 2115 __ CallStub(&stub); |
| 2053 RecordJSReturnSite(expr); | 2116 RecordJSReturnSite(expr); |
| 2054 // Restore context register. | 2117 // Restore context register. |
| 2055 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 2118 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 2119 |
| 2120 decrement_stack_height(arg_count + 1); |
| 2056 context()->DropAndPlug(1, eax); | 2121 context()->DropAndPlug(1, eax); |
| 2057 } | 2122 } |
| 2058 | 2123 |
| 2059 | 2124 |
| 2060 void FullCodeGenerator::EmitResolvePossiblyDirectEval(ResolveEvalFlag flag, | 2125 void FullCodeGenerator::EmitResolvePossiblyDirectEval(ResolveEvalFlag flag, |
| 2061 int arg_count) { | 2126 int arg_count) { |
| 2062 // Push copy of the first argument or undefined if it doesn't exist. | 2127 // Push copy of the first argument or undefined if it doesn't exist. |
| 2063 if (arg_count > 0) { | 2128 if (arg_count > 0) { |
| 2064 __ push(Operand(esp, arg_count * kPointerSize)); | 2129 __ push(Operand(esp, arg_count * kPointerSize)); |
| 2065 } else { | 2130 } else { |
| (...skipping 27 matching lines...) Expand all Loading... |
| 2093 // In a call to eval, we first call %ResolvePossiblyDirectEval to | 2158 // In a call to eval, we first call %ResolvePossiblyDirectEval to |
| 2094 // resolve the function we need to call and the receiver of the | 2159 // resolve the function we need to call and the receiver of the |
| 2095 // call. Then we call the resolved function using the given | 2160 // call. Then we call the resolved function using the given |
| 2096 // arguments. | 2161 // arguments. |
| 2097 ZoneList<Expression*>* args = expr->arguments(); | 2162 ZoneList<Expression*>* args = expr->arguments(); |
| 2098 int arg_count = args->length(); | 2163 int arg_count = args->length(); |
| 2099 { PreservePositionScope pos_scope(masm()->positions_recorder()); | 2164 { PreservePositionScope pos_scope(masm()->positions_recorder()); |
| 2100 VisitForStackValue(fun); | 2165 VisitForStackValue(fun); |
| 2101 // Reserved receiver slot. | 2166 // Reserved receiver slot. |
| 2102 __ push(Immediate(isolate()->factory()->undefined_value())); | 2167 __ push(Immediate(isolate()->factory()->undefined_value())); |
| 2103 | 2168 increment_stack_height(); |
| 2104 // Push the arguments. | 2169 // Push the arguments. |
| 2105 for (int i = 0; i < arg_count; i++) { | 2170 for (int i = 0; i < arg_count; i++) { |
| 2106 VisitForStackValue(args->at(i)); | 2171 VisitForStackValue(args->at(i)); |
| 2107 } | 2172 } |
| 2108 | 2173 |
| 2109 // If we know that eval can only be shadowed by eval-introduced | 2174 // If we know that eval can only be shadowed by eval-introduced |
| 2110 // variables we attempt to load the global eval function directly | 2175 // variables we attempt to load the global eval function directly |
| 2111 // in generated code. If we succeed, there is no need to perform a | 2176 // in generated code. If we succeed, there is no need to perform a |
| 2112 // context lookup in the runtime system. | 2177 // context lookup in the runtime system. |
| 2113 Label done; | 2178 Label done; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 2137 __ mov(Operand(esp, (arg_count + 1) * kPointerSize), eax); | 2202 __ mov(Operand(esp, (arg_count + 1) * kPointerSize), eax); |
| 2138 } | 2203 } |
| 2139 // Record source position for debugger. | 2204 // Record source position for debugger. |
| 2140 SetSourcePosition(expr->position()); | 2205 SetSourcePosition(expr->position()); |
| 2141 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; | 2206 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; |
| 2142 CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_IMPLICIT); | 2207 CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_IMPLICIT); |
| 2143 __ CallStub(&stub); | 2208 __ CallStub(&stub); |
| 2144 RecordJSReturnSite(expr); | 2209 RecordJSReturnSite(expr); |
| 2145 // Restore context register. | 2210 // Restore context register. |
| 2146 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 2211 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 2212 decrement_stack_height(arg_count + 1); // Function is left on the stack. |
| 2147 context()->DropAndPlug(1, eax); | 2213 context()->DropAndPlug(1, eax); |
| 2148 } else if (var != NULL && !var->is_this() && var->is_global()) { | 2214 } else if (var != NULL && !var->is_this() && var->is_global()) { |
| 2149 // Push global object as receiver for the call IC. | 2215 // Push global object as receiver for the call IC. |
| 2150 __ push(GlobalObjectOperand()); | 2216 __ push(GlobalObjectOperand()); |
| 2217 increment_stack_height(); |
| 2151 EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT); | 2218 EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT); |
| 2152 } else if (var != NULL && var->AsSlot() != NULL && | 2219 } else if (var != NULL && var->AsSlot() != NULL && |
| 2153 var->AsSlot()->type() == Slot::LOOKUP) { | 2220 var->AsSlot()->type() == Slot::LOOKUP) { |
| 2154 // Call to a lookup slot (dynamically introduced variable). | 2221 // Call to a lookup slot (dynamically introduced variable). |
| 2155 Label slow, done; | 2222 Label slow, done; |
| 2156 | 2223 |
| 2157 { PreservePositionScope scope(masm()->positions_recorder()); | 2224 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2158 // Generate code for loading from variables potentially shadowed | 2225 // Generate code for loading from variables potentially shadowed |
| 2159 // by eval-introduced variables. | 2226 // by eval-introduced variables. |
| 2160 EmitDynamicLoadFromSlotFastCase(var->AsSlot(), | 2227 EmitDynamicLoadFromSlotFastCase(var->AsSlot(), |
| 2161 NOT_INSIDE_TYPEOF, | 2228 NOT_INSIDE_TYPEOF, |
| 2162 &slow, | 2229 &slow, |
| 2163 &done); | 2230 &done); |
| 2164 } | 2231 } |
| 2165 | 2232 |
| 2166 __ bind(&slow); | 2233 __ bind(&slow); |
| 2167 // Call the runtime to find the function to call (returned in eax) | 2234 // Call the runtime to find the function to call (returned in eax) |
| 2168 // and the object holding it (returned in edx). | 2235 // and the object holding it (returned in edx). |
| 2169 __ push(context_register()); | 2236 __ push(context_register()); |
| 2170 __ push(Immediate(var->name())); | 2237 __ push(Immediate(var->name())); |
| 2171 __ CallRuntime(Runtime::kLoadContextSlot, 2); | 2238 __ CallRuntime(Runtime::kLoadContextSlot, 2); |
| 2172 __ push(eax); // Function. | 2239 __ push(eax); // Function. |
| 2240 increment_stack_height(); |
| 2173 __ push(edx); // Receiver. | 2241 __ push(edx); // Receiver. |
| 2242 increment_stack_height(); |
| 2174 | 2243 |
| 2175 // If fast case code has been generated, emit code to push the | 2244 // If fast case code has been generated, emit code to push the |
| 2176 // function and receiver and have the slow path jump around this | 2245 // function and receiver and have the slow path jump around this |
| 2177 // code. | 2246 // code. |
| 2178 if (done.is_linked()) { | 2247 if (done.is_linked()) { |
| 2179 Label call; | 2248 Label call; |
| 2180 __ jmp(&call); | 2249 __ jmp(&call); |
| 2181 __ bind(&done); | 2250 __ bind(&done); |
| 2182 // Push function. | 2251 // Push function. Stack height already incremented in slow case above. |
| 2183 __ push(eax); | 2252 __ push(eax); |
| 2184 // The receiver is implicitly the global receiver. Indicate this | 2253 // The receiver is implicitly the global receiver. Indicate this |
| 2185 // by passing the hole to the call function stub. | 2254 // by passing the hole to the call function stub. |
| 2186 __ push(Immediate(isolate()->factory()->the_hole_value())); | 2255 __ push(Immediate(isolate()->factory()->the_hole_value())); |
| 2187 __ bind(&call); | 2256 __ bind(&call); |
| 2188 } | 2257 } |
| 2189 | 2258 |
| 2190 // The receiver is either the global receiver or an object found | 2259 // The receiver is either the global receiver or an object found |
| 2191 // by LoadContextSlot. That object could be the hole if the | 2260 // by LoadContextSlot. That object could be the hole if the |
| 2192 // receiver is implicitly the global object. | 2261 // receiver is implicitly the global object. |
| (...skipping 25 matching lines...) Expand all Loading... |
| 2218 ASSERT(prop->key()->AsLiteral()->handle()->IsSmi()); | 2287 ASSERT(prop->key()->AsLiteral()->handle()->IsSmi()); |
| 2219 __ mov(eax, prop->key()->AsLiteral()->handle()); | 2288 __ mov(eax, prop->key()->AsLiteral()->handle()); |
| 2220 | 2289 |
| 2221 // Record source code position for IC call. | 2290 // Record source code position for IC call. |
| 2222 SetSourcePosition(prop->position()); | 2291 SetSourcePosition(prop->position()); |
| 2223 | 2292 |
| 2224 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); | 2293 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); |
| 2225 __ call(ic, RelocInfo::CODE_TARGET, GetPropertyId(prop)); | 2294 __ call(ic, RelocInfo::CODE_TARGET, GetPropertyId(prop)); |
| 2226 // Push result (function). | 2295 // Push result (function). |
| 2227 __ push(eax); | 2296 __ push(eax); |
| 2297 increment_stack_height(); |
| 2228 // Push Global receiver. | 2298 // Push Global receiver. |
| 2229 __ mov(ecx, GlobalObjectOperand()); | 2299 __ mov(ecx, GlobalObjectOperand()); |
| 2230 __ push(FieldOperand(ecx, GlobalObject::kGlobalReceiverOffset)); | 2300 __ push(FieldOperand(ecx, GlobalObject::kGlobalReceiverOffset)); |
| 2301 increment_stack_height(); |
| 2231 EmitCallWithStub(expr, NO_CALL_FUNCTION_FLAGS); | 2302 EmitCallWithStub(expr, NO_CALL_FUNCTION_FLAGS); |
| 2232 } else { | 2303 } else { |
| 2233 { PreservePositionScope scope(masm()->positions_recorder()); | 2304 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2234 VisitForStackValue(prop->obj()); | 2305 VisitForStackValue(prop->obj()); |
| 2235 } | 2306 } |
| 2236 EmitKeyedCallWithIC(expr, prop->key()); | 2307 EmitKeyedCallWithIC(expr, prop->key()); |
| 2237 } | 2308 } |
| 2238 } | 2309 } |
| 2239 } else { | 2310 } else { |
| 2240 { PreservePositionScope scope(masm()->positions_recorder()); | 2311 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2241 VisitForStackValue(fun); | 2312 VisitForStackValue(fun); |
| 2242 } | 2313 } |
| 2243 // Load global receiver object. | 2314 // Load global receiver object. |
| 2244 __ mov(ebx, GlobalObjectOperand()); | 2315 __ mov(ebx, GlobalObjectOperand()); |
| 2245 __ push(FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset)); | 2316 __ push(FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset)); |
| 2317 increment_stack_height(); |
| 2246 // Emit function call. | 2318 // Emit function call. |
| 2247 EmitCallWithStub(expr, NO_CALL_FUNCTION_FLAGS); | 2319 EmitCallWithStub(expr, NO_CALL_FUNCTION_FLAGS); |
| 2248 } | 2320 } |
| 2249 | 2321 |
| 2250 #ifdef DEBUG | 2322 #ifdef DEBUG |
| 2251 // RecordJSReturnSite should have been called. | 2323 // RecordJSReturnSite should have been called. |
| 2252 ASSERT(expr->return_is_recorded_); | 2324 ASSERT(expr->return_is_recorded_); |
| 2253 #endif | 2325 #endif |
| 2254 } | 2326 } |
| 2255 | 2327 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 2276 // constructor invocation. | 2348 // constructor invocation. |
| 2277 SetSourcePosition(expr->position()); | 2349 SetSourcePosition(expr->position()); |
| 2278 | 2350 |
| 2279 // Load function and argument count into edi and eax. | 2351 // Load function and argument count into edi and eax. |
| 2280 __ SafeSet(eax, Immediate(arg_count)); | 2352 __ SafeSet(eax, Immediate(arg_count)); |
| 2281 __ mov(edi, Operand(esp, arg_count * kPointerSize)); | 2353 __ mov(edi, Operand(esp, arg_count * kPointerSize)); |
| 2282 | 2354 |
| 2283 Handle<Code> construct_builtin = | 2355 Handle<Code> construct_builtin = |
| 2284 isolate()->builtins()->JSConstructCall(); | 2356 isolate()->builtins()->JSConstructCall(); |
| 2285 __ call(construct_builtin, RelocInfo::CONSTRUCT_CALL); | 2357 __ call(construct_builtin, RelocInfo::CONSTRUCT_CALL); |
| 2358 |
| 2359 decrement_stack_height(arg_count + 1); |
| 2286 context()->Plug(eax); | 2360 context()->Plug(eax); |
| 2287 } | 2361 } |
| 2288 | 2362 |
| 2289 | 2363 |
| 2290 void FullCodeGenerator::EmitIsSmi(ZoneList<Expression*>* args) { | 2364 void FullCodeGenerator::EmitIsSmi(ZoneList<Expression*>* args) { |
| 2291 ASSERT(args->length() == 1); | 2365 ASSERT(args->length() == 1); |
| 2292 | 2366 |
| 2293 VisitForAccumulatorValue(args->at(0)); | 2367 VisitForAccumulatorValue(args->at(0)); |
| 2294 | 2368 |
| 2295 Label materialize_true, materialize_false; | 2369 Label materialize_true, materialize_false; |
| (...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2588 VisitForAccumulatorValue(args->at(1)); | 2662 VisitForAccumulatorValue(args->at(1)); |
| 2589 | 2663 |
| 2590 Label materialize_true, materialize_false; | 2664 Label materialize_true, materialize_false; |
| 2591 Label* if_true = NULL; | 2665 Label* if_true = NULL; |
| 2592 Label* if_false = NULL; | 2666 Label* if_false = NULL; |
| 2593 Label* fall_through = NULL; | 2667 Label* fall_through = NULL; |
| 2594 context()->PrepareTest(&materialize_true, &materialize_false, | 2668 context()->PrepareTest(&materialize_true, &materialize_false, |
| 2595 &if_true, &if_false, &fall_through); | 2669 &if_true, &if_false, &fall_through); |
| 2596 | 2670 |
| 2597 __ pop(ebx); | 2671 __ pop(ebx); |
| 2672 decrement_stack_height(); |
| 2598 __ cmp(eax, Operand(ebx)); | 2673 __ cmp(eax, Operand(ebx)); |
| 2599 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); | 2674 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); |
| 2600 Split(equal, if_true, if_false, fall_through); | 2675 Split(equal, if_true, if_false, fall_through); |
| 2601 | 2676 |
| 2602 context()->Plug(if_true, if_false); | 2677 context()->Plug(if_true, if_false); |
| 2603 } | 2678 } |
| 2604 | 2679 |
| 2605 | 2680 |
| 2606 void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) { | 2681 void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) { |
| 2607 ASSERT(args->length() == 1); | 2682 ASSERT(args->length() == 1); |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2702 // 0 (literal string): The type of logging (corresponds to the flags). | 2777 // 0 (literal string): The type of logging (corresponds to the flags). |
| 2703 // This is used to determine whether or not to generate the log call. | 2778 // This is used to determine whether or not to generate the log call. |
| 2704 // 1 (string): Format string. Access the string at argument index 2 | 2779 // 1 (string): Format string. Access the string at argument index 2 |
| 2705 // with '%2s' (see Logger::LogRuntime for all the formats). | 2780 // with '%2s' (see Logger::LogRuntime for all the formats). |
| 2706 // 2 (array): Arguments to the format string. | 2781 // 2 (array): Arguments to the format string. |
| 2707 ASSERT_EQ(args->length(), 3); | 2782 ASSERT_EQ(args->length(), 3); |
| 2708 if (CodeGenerator::ShouldGenerateLog(args->at(0))) { | 2783 if (CodeGenerator::ShouldGenerateLog(args->at(0))) { |
| 2709 VisitForStackValue(args->at(1)); | 2784 VisitForStackValue(args->at(1)); |
| 2710 VisitForStackValue(args->at(2)); | 2785 VisitForStackValue(args->at(2)); |
| 2711 __ CallRuntime(Runtime::kLog, 2); | 2786 __ CallRuntime(Runtime::kLog, 2); |
| 2787 decrement_stack_height(2); |
| 2712 } | 2788 } |
| 2713 // Finally, we're expected to leave a value on the top of the stack. | 2789 // Finally, we're expected to leave a value on the top of the stack. |
| 2714 __ mov(eax, isolate()->factory()->undefined_value()); | 2790 __ mov(eax, isolate()->factory()->undefined_value()); |
| 2715 context()->Plug(eax); | 2791 context()->Plug(eax); |
| 2716 } | 2792 } |
| 2717 | 2793 |
| 2718 | 2794 |
| 2719 void FullCodeGenerator::EmitRandomHeapNumber(ZoneList<Expression*>* args) { | 2795 void FullCodeGenerator::EmitRandomHeapNumber(ZoneList<Expression*>* args) { |
| 2720 ASSERT(args->length() == 0); | 2796 ASSERT(args->length() == 0); |
| 2721 | 2797 |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2767 | 2843 |
| 2768 | 2844 |
| 2769 void FullCodeGenerator::EmitSubString(ZoneList<Expression*>* args) { | 2845 void FullCodeGenerator::EmitSubString(ZoneList<Expression*>* args) { |
| 2770 // Load the arguments on the stack and call the stub. | 2846 // Load the arguments on the stack and call the stub. |
| 2771 SubStringStub stub; | 2847 SubStringStub stub; |
| 2772 ASSERT(args->length() == 3); | 2848 ASSERT(args->length() == 3); |
| 2773 VisitForStackValue(args->at(0)); | 2849 VisitForStackValue(args->at(0)); |
| 2774 VisitForStackValue(args->at(1)); | 2850 VisitForStackValue(args->at(1)); |
| 2775 VisitForStackValue(args->at(2)); | 2851 VisitForStackValue(args->at(2)); |
| 2776 __ CallStub(&stub); | 2852 __ CallStub(&stub); |
| 2853 decrement_stack_height(3); |
| 2777 context()->Plug(eax); | 2854 context()->Plug(eax); |
| 2778 } | 2855 } |
| 2779 | 2856 |
| 2780 | 2857 |
| 2781 void FullCodeGenerator::EmitRegExpExec(ZoneList<Expression*>* args) { | 2858 void FullCodeGenerator::EmitRegExpExec(ZoneList<Expression*>* args) { |
| 2782 // Load the arguments on the stack and call the stub. | 2859 // Load the arguments on the stack and call the stub. |
| 2783 RegExpExecStub stub; | 2860 RegExpExecStub stub; |
| 2784 ASSERT(args->length() == 4); | 2861 ASSERT(args->length() == 4); |
| 2785 VisitForStackValue(args->at(0)); | 2862 VisitForStackValue(args->at(0)); |
| 2786 VisitForStackValue(args->at(1)); | 2863 VisitForStackValue(args->at(1)); |
| 2787 VisitForStackValue(args->at(2)); | 2864 VisitForStackValue(args->at(2)); |
| 2788 VisitForStackValue(args->at(3)); | 2865 VisitForStackValue(args->at(3)); |
| 2789 __ CallStub(&stub); | 2866 __ CallStub(&stub); |
| 2867 decrement_stack_height(4); |
| 2790 context()->Plug(eax); | 2868 context()->Plug(eax); |
| 2791 } | 2869 } |
| 2792 | 2870 |
| 2793 | 2871 |
| 2794 void FullCodeGenerator::EmitValueOf(ZoneList<Expression*>* args) { | 2872 void FullCodeGenerator::EmitValueOf(ZoneList<Expression*>* args) { |
| 2795 ASSERT(args->length() == 1); | 2873 ASSERT(args->length() == 1); |
| 2796 | 2874 |
| 2797 VisitForAccumulatorValue(args->at(0)); // Load the object. | 2875 VisitForAccumulatorValue(args->at(0)); // Load the object. |
| 2798 | 2876 |
| 2799 Label done; | 2877 Label done; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 2814 ASSERT(args->length() == 2); | 2892 ASSERT(args->length() == 2); |
| 2815 VisitForStackValue(args->at(0)); | 2893 VisitForStackValue(args->at(0)); |
| 2816 VisitForStackValue(args->at(1)); | 2894 VisitForStackValue(args->at(1)); |
| 2817 | 2895 |
| 2818 if (CpuFeatures::IsSupported(SSE2)) { | 2896 if (CpuFeatures::IsSupported(SSE2)) { |
| 2819 MathPowStub stub; | 2897 MathPowStub stub; |
| 2820 __ CallStub(&stub); | 2898 __ CallStub(&stub); |
| 2821 } else { | 2899 } else { |
| 2822 __ CallRuntime(Runtime::kMath_pow, 2); | 2900 __ CallRuntime(Runtime::kMath_pow, 2); |
| 2823 } | 2901 } |
| 2902 decrement_stack_height(2); |
| 2824 context()->Plug(eax); | 2903 context()->Plug(eax); |
| 2825 } | 2904 } |
| 2826 | 2905 |
| 2827 | 2906 |
| 2828 void FullCodeGenerator::EmitSetValueOf(ZoneList<Expression*>* args) { | 2907 void FullCodeGenerator::EmitSetValueOf(ZoneList<Expression*>* args) { |
| 2829 ASSERT(args->length() == 2); | 2908 ASSERT(args->length() == 2); |
| 2830 | 2909 |
| 2831 VisitForStackValue(args->at(0)); // Load the object. | 2910 VisitForStackValue(args->at(0)); // Load the object. |
| 2832 VisitForAccumulatorValue(args->at(1)); // Load the value. | 2911 VisitForAccumulatorValue(args->at(1)); // Load the value. |
| 2833 __ pop(ebx); // eax = value. ebx = object. | 2912 __ pop(ebx); // eax = value. ebx = object. |
| 2913 decrement_stack_height(); |
| 2834 | 2914 |
| 2835 Label done; | 2915 Label done; |
| 2836 // If the object is a smi, return the value. | 2916 // If the object is a smi, return the value. |
| 2837 __ JumpIfSmi(ebx, &done, Label::kNear); | 2917 __ JumpIfSmi(ebx, &done, Label::kNear); |
| 2838 | 2918 |
| 2839 // If the object is not a value type, return the value. | 2919 // If the object is not a value type, return the value. |
| 2840 __ CmpObjectType(ebx, JS_VALUE_TYPE, ecx); | 2920 __ CmpObjectType(ebx, JS_VALUE_TYPE, ecx); |
| 2841 __ j(not_equal, &done, Label::kNear); | 2921 __ j(not_equal, &done, Label::kNear); |
| 2842 | 2922 |
| 2843 // Store the value. | 2923 // Store the value. |
| 2844 __ mov(FieldOperand(ebx, JSValue::kValueOffset), eax); | 2924 __ mov(FieldOperand(ebx, JSValue::kValueOffset), eax); |
| 2845 // Update the write barrier. Save the value as it will be | 2925 // Update the write barrier. Save the value as it will be |
| 2846 // overwritten by the write barrier code and is needed afterward. | 2926 // overwritten by the write barrier code and is needed afterward. |
| 2847 __ mov(edx, eax); | 2927 __ mov(edx, eax); |
| 2848 __ RecordWrite(ebx, JSValue::kValueOffset, edx, ecx); | 2928 __ RecordWrite(ebx, JSValue::kValueOffset, edx, ecx); |
| 2849 | 2929 |
| 2850 __ bind(&done); | 2930 __ bind(&done); |
| 2851 context()->Plug(eax); | 2931 context()->Plug(eax); |
| 2852 } | 2932 } |
| 2853 | 2933 |
| 2854 | 2934 |
| 2855 void FullCodeGenerator::EmitNumberToString(ZoneList<Expression*>* args) { | 2935 void FullCodeGenerator::EmitNumberToString(ZoneList<Expression*>* args) { |
| 2856 ASSERT_EQ(args->length(), 1); | 2936 ASSERT_EQ(args->length(), 1); |
| 2857 | 2937 |
| 2858 // Load the argument on the stack and call the stub. | 2938 // Load the argument on the stack and call the stub. |
| 2859 VisitForStackValue(args->at(0)); | 2939 VisitForStackValue(args->at(0)); |
| 2860 | 2940 |
| 2861 NumberToStringStub stub; | 2941 NumberToStringStub stub; |
| 2862 __ CallStub(&stub); | 2942 __ CallStub(&stub); |
| 2943 decrement_stack_height(); |
| 2863 context()->Plug(eax); | 2944 context()->Plug(eax); |
| 2864 } | 2945 } |
| 2865 | 2946 |
| 2866 | 2947 |
| 2867 void FullCodeGenerator::EmitStringCharFromCode(ZoneList<Expression*>* args) { | 2948 void FullCodeGenerator::EmitStringCharFromCode(ZoneList<Expression*>* args) { |
| 2868 ASSERT(args->length() == 1); | 2949 ASSERT(args->length() == 1); |
| 2869 | 2950 |
| 2870 VisitForAccumulatorValue(args->at(0)); | 2951 VisitForAccumulatorValue(args->at(0)); |
| 2871 | 2952 |
| 2872 Label done; | 2953 Label done; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 2887 | 2968 |
| 2888 VisitForStackValue(args->at(0)); | 2969 VisitForStackValue(args->at(0)); |
| 2889 VisitForAccumulatorValue(args->at(1)); | 2970 VisitForAccumulatorValue(args->at(1)); |
| 2890 | 2971 |
| 2891 Register object = ebx; | 2972 Register object = ebx; |
| 2892 Register index = eax; | 2973 Register index = eax; |
| 2893 Register scratch = ecx; | 2974 Register scratch = ecx; |
| 2894 Register result = edx; | 2975 Register result = edx; |
| 2895 | 2976 |
| 2896 __ pop(object); | 2977 __ pop(object); |
| 2978 decrement_stack_height(); |
| 2897 | 2979 |
| 2898 Label need_conversion; | 2980 Label need_conversion; |
| 2899 Label index_out_of_range; | 2981 Label index_out_of_range; |
| 2900 Label done; | 2982 Label done; |
| 2901 StringCharCodeAtGenerator generator(object, | 2983 StringCharCodeAtGenerator generator(object, |
| 2902 index, | 2984 index, |
| 2903 scratch, | 2985 scratch, |
| 2904 result, | 2986 result, |
| 2905 &need_conversion, | 2987 &need_conversion, |
| 2906 &need_conversion, | 2988 &need_conversion, |
| (...skipping 28 matching lines...) Expand all Loading... |
| 2935 VisitForStackValue(args->at(0)); | 3017 VisitForStackValue(args->at(0)); |
| 2936 VisitForAccumulatorValue(args->at(1)); | 3018 VisitForAccumulatorValue(args->at(1)); |
| 2937 | 3019 |
| 2938 Register object = ebx; | 3020 Register object = ebx; |
| 2939 Register index = eax; | 3021 Register index = eax; |
| 2940 Register scratch1 = ecx; | 3022 Register scratch1 = ecx; |
| 2941 Register scratch2 = edx; | 3023 Register scratch2 = edx; |
| 2942 Register result = eax; | 3024 Register result = eax; |
| 2943 | 3025 |
| 2944 __ pop(object); | 3026 __ pop(object); |
| 3027 decrement_stack_height(); |
| 2945 | 3028 |
| 2946 Label need_conversion; | 3029 Label need_conversion; |
| 2947 Label index_out_of_range; | 3030 Label index_out_of_range; |
| 2948 Label done; | 3031 Label done; |
| 2949 StringCharAtGenerator generator(object, | 3032 StringCharAtGenerator generator(object, |
| 2950 index, | 3033 index, |
| 2951 scratch1, | 3034 scratch1, |
| 2952 scratch2, | 3035 scratch2, |
| 2953 result, | 3036 result, |
| 2954 &need_conversion, | 3037 &need_conversion, |
| (...skipping 24 matching lines...) Expand all Loading... |
| 2979 | 3062 |
| 2980 | 3063 |
| 2981 void FullCodeGenerator::EmitStringAdd(ZoneList<Expression*>* args) { | 3064 void FullCodeGenerator::EmitStringAdd(ZoneList<Expression*>* args) { |
| 2982 ASSERT_EQ(2, args->length()); | 3065 ASSERT_EQ(2, args->length()); |
| 2983 | 3066 |
| 2984 VisitForStackValue(args->at(0)); | 3067 VisitForStackValue(args->at(0)); |
| 2985 VisitForStackValue(args->at(1)); | 3068 VisitForStackValue(args->at(1)); |
| 2986 | 3069 |
| 2987 StringAddStub stub(NO_STRING_ADD_FLAGS); | 3070 StringAddStub stub(NO_STRING_ADD_FLAGS); |
| 2988 __ CallStub(&stub); | 3071 __ CallStub(&stub); |
| 3072 decrement_stack_height(2); |
| 2989 context()->Plug(eax); | 3073 context()->Plug(eax); |
| 2990 } | 3074 } |
| 2991 | 3075 |
| 2992 | 3076 |
| 2993 void FullCodeGenerator::EmitStringCompare(ZoneList<Expression*>* args) { | 3077 void FullCodeGenerator::EmitStringCompare(ZoneList<Expression*>* args) { |
| 2994 ASSERT_EQ(2, args->length()); | 3078 ASSERT_EQ(2, args->length()); |
| 2995 | 3079 |
| 2996 VisitForStackValue(args->at(0)); | 3080 VisitForStackValue(args->at(0)); |
| 2997 VisitForStackValue(args->at(1)); | 3081 VisitForStackValue(args->at(1)); |
| 2998 | 3082 |
| 2999 StringCompareStub stub; | 3083 StringCompareStub stub; |
| 3000 __ CallStub(&stub); | 3084 __ CallStub(&stub); |
| 3085 decrement_stack_height(2); |
| 3001 context()->Plug(eax); | 3086 context()->Plug(eax); |
| 3002 } | 3087 } |
| 3003 | 3088 |
| 3004 | 3089 |
| 3005 void FullCodeGenerator::EmitMathSin(ZoneList<Expression*>* args) { | 3090 void FullCodeGenerator::EmitMathSin(ZoneList<Expression*>* args) { |
| 3006 // Load the argument on the stack and call the stub. | 3091 // Load the argument on the stack and call the stub. |
| 3007 TranscendentalCacheStub stub(TranscendentalCache::SIN, | 3092 TranscendentalCacheStub stub(TranscendentalCache::SIN, |
| 3008 TranscendentalCacheStub::TAGGED); | 3093 TranscendentalCacheStub::TAGGED); |
| 3009 ASSERT(args->length() == 1); | 3094 ASSERT(args->length() == 1); |
| 3010 VisitForStackValue(args->at(0)); | 3095 VisitForStackValue(args->at(0)); |
| 3011 __ CallStub(&stub); | 3096 __ CallStub(&stub); |
| 3097 decrement_stack_height(); |
| 3012 context()->Plug(eax); | 3098 context()->Plug(eax); |
| 3013 } | 3099 } |
| 3014 | 3100 |
| 3015 | 3101 |
| 3016 void FullCodeGenerator::EmitMathCos(ZoneList<Expression*>* args) { | 3102 void FullCodeGenerator::EmitMathCos(ZoneList<Expression*>* args) { |
| 3017 // Load the argument on the stack and call the stub. | 3103 // Load the argument on the stack and call the stub. |
| 3018 TranscendentalCacheStub stub(TranscendentalCache::COS, | 3104 TranscendentalCacheStub stub(TranscendentalCache::COS, |
| 3019 TranscendentalCacheStub::TAGGED); | 3105 TranscendentalCacheStub::TAGGED); |
| 3020 ASSERT(args->length() == 1); | 3106 ASSERT(args->length() == 1); |
| 3021 VisitForStackValue(args->at(0)); | 3107 VisitForStackValue(args->at(0)); |
| 3022 __ CallStub(&stub); | 3108 __ CallStub(&stub); |
| 3109 decrement_stack_height(); |
| 3023 context()->Plug(eax); | 3110 context()->Plug(eax); |
| 3024 } | 3111 } |
| 3025 | 3112 |
| 3026 | 3113 |
| 3027 void FullCodeGenerator::EmitMathLog(ZoneList<Expression*>* args) { | 3114 void FullCodeGenerator::EmitMathLog(ZoneList<Expression*>* args) { |
| 3028 // Load the argument on the stack and call the stub. | 3115 // Load the argument on the stack and call the stub. |
| 3029 TranscendentalCacheStub stub(TranscendentalCache::LOG, | 3116 TranscendentalCacheStub stub(TranscendentalCache::LOG, |
| 3030 TranscendentalCacheStub::TAGGED); | 3117 TranscendentalCacheStub::TAGGED); |
| 3031 ASSERT(args->length() == 1); | 3118 ASSERT(args->length() == 1); |
| 3032 VisitForStackValue(args->at(0)); | 3119 VisitForStackValue(args->at(0)); |
| 3033 __ CallStub(&stub); | 3120 __ CallStub(&stub); |
| 3121 decrement_stack_height(); |
| 3034 context()->Plug(eax); | 3122 context()->Plug(eax); |
| 3035 } | 3123 } |
| 3036 | 3124 |
| 3037 | 3125 |
| 3038 void FullCodeGenerator::EmitMathSqrt(ZoneList<Expression*>* args) { | 3126 void FullCodeGenerator::EmitMathSqrt(ZoneList<Expression*>* args) { |
| 3039 // Load the argument on the stack and call the runtime function. | 3127 // Load the argument on the stack and call the runtime function. |
| 3040 ASSERT(args->length() == 1); | 3128 ASSERT(args->length() == 1); |
| 3041 VisitForStackValue(args->at(0)); | 3129 VisitForStackValue(args->at(0)); |
| 3042 __ CallRuntime(Runtime::kMath_sqrt, 1); | 3130 __ CallRuntime(Runtime::kMath_sqrt, 1); |
| 3131 decrement_stack_height(); |
| 3043 context()->Plug(eax); | 3132 context()->Plug(eax); |
| 3044 } | 3133 } |
| 3045 | 3134 |
| 3046 | 3135 |
| 3047 void FullCodeGenerator::EmitCallFunction(ZoneList<Expression*>* args) { | 3136 void FullCodeGenerator::EmitCallFunction(ZoneList<Expression*>* args) { |
| 3048 ASSERT(args->length() >= 2); | 3137 ASSERT(args->length() >= 2); |
| 3049 | 3138 |
| 3050 int arg_count = args->length() - 2; // 2 ~ receiver and function. | 3139 int arg_count = args->length() - 2; // 2 ~ receiver and function. |
| 3051 for (int i = 0; i < arg_count + 1; ++i) { | 3140 for (int i = 0; i < arg_count + 1; ++i) { |
| 3052 VisitForStackValue(args->at(i)); | 3141 VisitForStackValue(args->at(i)); |
| 3053 } | 3142 } |
| 3054 VisitForAccumulatorValue(args->last()); // Function. | 3143 VisitForAccumulatorValue(args->last()); // Function. |
| 3055 | 3144 |
| 3056 // InvokeFunction requires the function in edi. Move it in there. | 3145 // InvokeFunction requires the function in edi. Move it in there. |
| 3057 __ mov(edi, result_register()); | 3146 __ mov(edi, result_register()); |
| 3058 ParameterCount count(arg_count); | 3147 ParameterCount count(arg_count); |
| 3059 __ InvokeFunction(edi, count, CALL_FUNCTION, | 3148 __ InvokeFunction(edi, count, CALL_FUNCTION, |
| 3060 NullCallWrapper(), CALL_AS_METHOD); | 3149 NullCallWrapper(), CALL_AS_METHOD); |
| 3061 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 3150 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 3151 decrement_stack_height(arg_count + 1); |
| 3062 context()->Plug(eax); | 3152 context()->Plug(eax); |
| 3063 } | 3153 } |
| 3064 | 3154 |
| 3065 | 3155 |
| 3066 void FullCodeGenerator::EmitRegExpConstructResult(ZoneList<Expression*>* args) { | 3156 void FullCodeGenerator::EmitRegExpConstructResult(ZoneList<Expression*>* args) { |
| 3067 // Load the arguments on the stack and call the stub. | 3157 // Load the arguments on the stack and call the stub. |
| 3068 RegExpConstructResultStub stub; | 3158 RegExpConstructResultStub stub; |
| 3069 ASSERT(args->length() == 3); | 3159 ASSERT(args->length() == 3); |
| 3070 VisitForStackValue(args->at(0)); | 3160 VisitForStackValue(args->at(0)); |
| 3071 VisitForStackValue(args->at(1)); | 3161 VisitForStackValue(args->at(1)); |
| 3072 VisitForStackValue(args->at(2)); | 3162 VisitForStackValue(args->at(2)); |
| 3073 __ CallStub(&stub); | 3163 __ CallStub(&stub); |
| 3164 decrement_stack_height(3); |
| 3074 context()->Plug(eax); | 3165 context()->Plug(eax); |
| 3075 } | 3166 } |
| 3076 | 3167 |
| 3077 | 3168 |
| 3078 void FullCodeGenerator::EmitSwapElements(ZoneList<Expression*>* args) { | 3169 void FullCodeGenerator::EmitSwapElements(ZoneList<Expression*>* args) { |
| 3079 ASSERT(args->length() == 3); | 3170 ASSERT(args->length() == 3); |
| 3080 VisitForStackValue(args->at(0)); | 3171 VisitForStackValue(args->at(0)); |
| 3081 VisitForStackValue(args->at(1)); | 3172 VisitForStackValue(args->at(1)); |
| 3082 VisitForStackValue(args->at(2)); | 3173 VisitForStackValue(args->at(2)); |
| 3083 Label done; | 3174 Label done; |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3137 __ bind(&new_space); | 3228 __ bind(&new_space); |
| 3138 // We are done. Drop elements from the stack, and return undefined. | 3229 // We are done. Drop elements from the stack, and return undefined. |
| 3139 __ add(Operand(esp), Immediate(3 * kPointerSize)); | 3230 __ add(Operand(esp), Immediate(3 * kPointerSize)); |
| 3140 __ mov(eax, isolate()->factory()->undefined_value()); | 3231 __ mov(eax, isolate()->factory()->undefined_value()); |
| 3141 __ jmp(&done); | 3232 __ jmp(&done); |
| 3142 | 3233 |
| 3143 __ bind(&slow_case); | 3234 __ bind(&slow_case); |
| 3144 __ CallRuntime(Runtime::kSwapElements, 3); | 3235 __ CallRuntime(Runtime::kSwapElements, 3); |
| 3145 | 3236 |
| 3146 __ bind(&done); | 3237 __ bind(&done); |
| 3238 decrement_stack_height(3); |
| 3147 context()->Plug(eax); | 3239 context()->Plug(eax); |
| 3148 } | 3240 } |
| 3149 | 3241 |
| 3150 | 3242 |
| 3151 void FullCodeGenerator::EmitGetFromCache(ZoneList<Expression*>* args) { | 3243 void FullCodeGenerator::EmitGetFromCache(ZoneList<Expression*>* args) { |
| 3152 ASSERT_EQ(2, args->length()); | 3244 ASSERT_EQ(2, args->length()); |
| 3153 | 3245 |
| 3154 ASSERT_NE(NULL, args->at(0)->AsLiteral()); | 3246 ASSERT_NE(NULL, args->at(0)->AsLiteral()); |
| 3155 int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->handle()))->value(); | 3247 int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->handle()))->value(); |
| 3156 | 3248 |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3222 __ mov(tmp, FieldOperand(left, JSRegExp::kDataOffset)); | 3314 __ mov(tmp, FieldOperand(left, JSRegExp::kDataOffset)); |
| 3223 __ cmp(tmp, FieldOperand(right, JSRegExp::kDataOffset)); | 3315 __ cmp(tmp, FieldOperand(right, JSRegExp::kDataOffset)); |
| 3224 __ j(equal, &ok); | 3316 __ j(equal, &ok); |
| 3225 __ bind(&fail); | 3317 __ bind(&fail); |
| 3226 __ mov(eax, Immediate(isolate()->factory()->false_value())); | 3318 __ mov(eax, Immediate(isolate()->factory()->false_value())); |
| 3227 __ jmp(&done); | 3319 __ jmp(&done); |
| 3228 __ bind(&ok); | 3320 __ bind(&ok); |
| 3229 __ mov(eax, Immediate(isolate()->factory()->true_value())); | 3321 __ mov(eax, Immediate(isolate()->factory()->true_value())); |
| 3230 __ bind(&done); | 3322 __ bind(&done); |
| 3231 | 3323 |
| 3324 decrement_stack_height(); |
| 3232 context()->Plug(eax); | 3325 context()->Plug(eax); |
| 3233 } | 3326 } |
| 3234 | 3327 |
| 3235 | 3328 |
| 3236 void FullCodeGenerator::EmitHasCachedArrayIndex(ZoneList<Expression*>* args) { | 3329 void FullCodeGenerator::EmitHasCachedArrayIndex(ZoneList<Expression*>* args) { |
| 3237 ASSERT(args->length() == 1); | 3330 ASSERT(args->length() == 1); |
| 3238 | 3331 |
| 3239 VisitForAccumulatorValue(args->at(0)); | 3332 VisitForAccumulatorValue(args->at(0)); |
| 3240 | 3333 |
| 3241 if (FLAG_debug_code) { | 3334 if (FLAG_debug_code) { |
| (...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3525 | 3618 |
| 3526 | 3619 |
| 3527 __ bind(&bailout); | 3620 __ bind(&bailout); |
| 3528 __ mov(result_operand, isolate()->factory()->undefined_value()); | 3621 __ mov(result_operand, isolate()->factory()->undefined_value()); |
| 3529 __ bind(&done); | 3622 __ bind(&done); |
| 3530 __ mov(eax, result_operand); | 3623 __ mov(eax, result_operand); |
| 3531 // Drop temp values from the stack, and restore context register. | 3624 // Drop temp values from the stack, and restore context register. |
| 3532 __ add(Operand(esp), Immediate(3 * kPointerSize)); | 3625 __ add(Operand(esp), Immediate(3 * kPointerSize)); |
| 3533 | 3626 |
| 3534 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 3627 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 3628 decrement_stack_height(); |
| 3535 context()->Plug(eax); | 3629 context()->Plug(eax); |
| 3536 } | 3630 } |
| 3537 | 3631 |
| 3538 | 3632 |
| 3539 void FullCodeGenerator::EmitIsNativeOrStrictMode(ZoneList<Expression*>* args) { | 3633 void FullCodeGenerator::EmitIsNativeOrStrictMode(ZoneList<Expression*>* args) { |
| 3540 ASSERT(args->length() == 1); | 3634 ASSERT(args->length() == 1); |
| 3541 | 3635 |
| 3542 // Load the function into eax. | 3636 // Load the function into eax. |
| 3543 VisitForAccumulatorValue(args->at(0)); | 3637 VisitForAccumulatorValue(args->at(0)); |
| 3544 | 3638 |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3577 return; | 3671 return; |
| 3578 } | 3672 } |
| 3579 | 3673 |
| 3580 Comment cmnt(masm_, "[ CallRuntime"); | 3674 Comment cmnt(masm_, "[ CallRuntime"); |
| 3581 ZoneList<Expression*>* args = expr->arguments(); | 3675 ZoneList<Expression*>* args = expr->arguments(); |
| 3582 | 3676 |
| 3583 if (expr->is_jsruntime()) { | 3677 if (expr->is_jsruntime()) { |
| 3584 // Prepare for calling JS runtime function. | 3678 // Prepare for calling JS runtime function. |
| 3585 __ mov(eax, GlobalObjectOperand()); | 3679 __ mov(eax, GlobalObjectOperand()); |
| 3586 __ push(FieldOperand(eax, GlobalObject::kBuiltinsOffset)); | 3680 __ push(FieldOperand(eax, GlobalObject::kBuiltinsOffset)); |
| 3681 increment_stack_height(); |
| 3587 } | 3682 } |
| 3588 | 3683 |
| 3589 // Push the arguments ("left-to-right"). | 3684 // Push the arguments ("left-to-right"). |
| 3590 int arg_count = args->length(); | 3685 int arg_count = args->length(); |
| 3591 for (int i = 0; i < arg_count; i++) { | 3686 for (int i = 0; i < arg_count; i++) { |
| 3592 VisitForStackValue(args->at(i)); | 3687 VisitForStackValue(args->at(i)); |
| 3593 } | 3688 } |
| 3594 | 3689 |
| 3595 if (expr->is_jsruntime()) { | 3690 if (expr->is_jsruntime()) { |
| 3596 // Call the JS runtime function via a call IC. | 3691 // Call the JS runtime function via a call IC. |
| 3597 __ Set(ecx, Immediate(expr->name())); | 3692 __ Set(ecx, Immediate(expr->name())); |
| 3598 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; | 3693 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; |
| 3599 RelocInfo::Mode mode = RelocInfo::CODE_TARGET; | 3694 RelocInfo::Mode mode = RelocInfo::CODE_TARGET; |
| 3600 Handle<Code> ic = isolate()->stub_cache()->ComputeCallInitialize( | 3695 Handle<Code> ic = isolate()->stub_cache()->ComputeCallInitialize( |
| 3601 arg_count, in_loop, mode); | 3696 arg_count, in_loop, mode); |
| 3602 __ call(ic, mode, expr->id()); | 3697 __ call(ic, mode, expr->id()); |
| 3603 // Restore context register. | 3698 // Restore context register. |
| 3604 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 3699 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 3605 } else { | 3700 } else { |
| 3606 // Call the C runtime function. | 3701 // Call the C runtime function. |
| 3607 __ CallRuntime(expr->function(), arg_count); | 3702 __ CallRuntime(expr->function(), arg_count); |
| 3608 } | 3703 } |
| 3704 decrement_stack_height(arg_count); |
| 3705 if (expr->is_jsruntime()) { |
| 3706 decrement_stack_height(); |
| 3707 } |
| 3708 |
| 3609 context()->Plug(eax); | 3709 context()->Plug(eax); |
| 3610 } | 3710 } |
| 3611 | 3711 |
| 3612 | 3712 |
| 3613 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { | 3713 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { |
| 3614 switch (expr->op()) { | 3714 switch (expr->op()) { |
| 3615 case Token::DELETE: { | 3715 case Token::DELETE: { |
| 3616 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); | 3716 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); |
| 3617 Property* prop = expr->expression()->AsProperty(); | 3717 Property* prop = expr->expression()->AsProperty(); |
| 3618 Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); | 3718 Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); |
| 3619 | 3719 |
| 3620 if (prop != NULL) { | 3720 if (prop != NULL) { |
| 3621 if (prop->is_synthetic()) { | 3721 if (prop->is_synthetic()) { |
| 3622 // Result of deleting parameters is false, even when they rewrite | 3722 // Result of deleting parameters is false, even when they rewrite |
| 3623 // to accesses on the arguments object. | 3723 // to accesses on the arguments object. |
| 3624 context()->Plug(false); | 3724 context()->Plug(false); |
| 3625 } else { | 3725 } else { |
| 3626 VisitForStackValue(prop->obj()); | 3726 VisitForStackValue(prop->obj()); |
| 3627 VisitForStackValue(prop->key()); | 3727 VisitForStackValue(prop->key()); |
| 3628 __ push(Immediate(Smi::FromInt(strict_mode_flag()))); | 3728 __ push(Immediate(Smi::FromInt(strict_mode_flag()))); |
| 3629 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); | 3729 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); |
| 3730 decrement_stack_height(2); |
| 3630 context()->Plug(eax); | 3731 context()->Plug(eax); |
| 3631 } | 3732 } |
| 3632 } else if (var != NULL) { | 3733 } else if (var != NULL) { |
| 3633 // Delete of an unqualified identifier is disallowed in strict mode | 3734 // Delete of an unqualified identifier is disallowed in strict mode |
| 3634 // but "delete this" is. | 3735 // but "delete this" is. |
| 3635 ASSERT(strict_mode_flag() == kNonStrictMode || var->is_this()); | 3736 ASSERT(strict_mode_flag() == kNonStrictMode || var->is_this()); |
| 3636 if (var->is_global()) { | 3737 if (var->is_global()) { |
| 3637 __ push(GlobalObjectOperand()); | 3738 __ push(GlobalObjectOperand()); |
| 3638 __ push(Immediate(var->name())); | 3739 __ push(Immediate(var->name())); |
| 3639 __ push(Immediate(Smi::FromInt(kNonStrictMode))); | 3740 __ push(Immediate(Smi::FromInt(kNonStrictMode))); |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3689 } | 3790 } |
| 3690 break; | 3791 break; |
| 3691 } | 3792 } |
| 3692 | 3793 |
| 3693 case Token::TYPEOF: { | 3794 case Token::TYPEOF: { |
| 3694 Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)"); | 3795 Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)"); |
| 3695 { StackValueContext context(this); | 3796 { StackValueContext context(this); |
| 3696 VisitForTypeofValue(expr->expression()); | 3797 VisitForTypeofValue(expr->expression()); |
| 3697 } | 3798 } |
| 3698 __ CallRuntime(Runtime::kTypeof, 1); | 3799 __ CallRuntime(Runtime::kTypeof, 1); |
| 3800 decrement_stack_height(); |
| 3699 context()->Plug(eax); | 3801 context()->Plug(eax); |
| 3700 break; | 3802 break; |
| 3701 } | 3803 } |
| 3702 | 3804 |
| 3703 case Token::ADD: { | 3805 case Token::ADD: { |
| 3704 Comment cmt(masm_, "[ UnaryOperation (ADD)"); | 3806 Comment cmt(masm_, "[ UnaryOperation (ADD)"); |
| 3705 VisitForAccumulatorValue(expr->expression()); | 3807 VisitForAccumulatorValue(expr->expression()); |
| 3706 Label no_conversion; | 3808 Label no_conversion; |
| 3707 __ JumpIfSmi(result_register(), &no_conversion); | 3809 __ JumpIfSmi(result_register(), &no_conversion); |
| 3708 ToNumberStub convert_stub; | 3810 ToNumberStub convert_stub; |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3743 } | 3845 } |
| 3744 | 3846 |
| 3745 | 3847 |
| 3746 void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { | 3848 void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { |
| 3747 Comment cmnt(masm_, "[ CountOperation"); | 3849 Comment cmnt(masm_, "[ CountOperation"); |
| 3748 SetSourcePosition(expr->position()); | 3850 SetSourcePosition(expr->position()); |
| 3749 | 3851 |
| 3750 // Invalid left-hand sides are rewritten to have a 'throw ReferenceError' | 3852 // Invalid left-hand sides are rewritten to have a 'throw ReferenceError' |
| 3751 // as the left-hand side. | 3853 // as the left-hand side. |
| 3752 if (!expr->expression()->IsValidLeftHandSide()) { | 3854 if (!expr->expression()->IsValidLeftHandSide()) { |
| 3753 VisitForEffect(expr->expression()); | 3855 ASSERT(expr->expression()->AsThrow() != NULL); |
| 3856 VisitInCurrentContext(expr->expression()); |
| 3857 // Visiting Throw does not plug the context. |
| 3858 context()->Plug(eax); |
| 3754 return; | 3859 return; |
| 3755 } | 3860 } |
| 3756 | 3861 |
| 3757 // Expression can only be a property, a global or a (parameter or local) | 3862 // Expression can only be a property, a global or a (parameter or local) |
| 3758 // slot. | 3863 // slot. |
| 3759 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; | 3864 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; |
| 3760 LhsKind assign_type = VARIABLE; | 3865 LhsKind assign_type = VARIABLE; |
| 3761 Property* prop = expr->expression()->AsProperty(); | 3866 Property* prop = expr->expression()->AsProperty(); |
| 3762 // In case of a property we use the uninitialized expression context | 3867 // In case of a property we use the uninitialized expression context |
| 3763 // of the key to detect a named property. | 3868 // of the key to detect a named property. |
| 3764 if (prop != NULL) { | 3869 if (prop != NULL) { |
| 3765 assign_type = | 3870 assign_type = |
| 3766 (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY; | 3871 (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY; |
| 3767 } | 3872 } |
| 3768 | 3873 |
| 3769 // Evaluate expression and get value. | 3874 // Evaluate expression and get value. |
| 3770 if (assign_type == VARIABLE) { | 3875 if (assign_type == VARIABLE) { |
| 3771 ASSERT(expr->expression()->AsVariableProxy()->var() != NULL); | 3876 ASSERT(expr->expression()->AsVariableProxy()->var() != NULL); |
| 3772 AccumulatorValueContext context(this); | 3877 AccumulatorValueContext context(this); |
| 3773 EmitVariableLoad(expr->expression()->AsVariableProxy()); | 3878 EmitVariableLoad(expr->expression()->AsVariableProxy()); |
| 3774 } else { | 3879 } else { |
| 3775 // Reserve space for result of postfix operation. | 3880 // Reserve space for result of postfix operation. |
| 3776 if (expr->is_postfix() && !context()->IsEffect()) { | 3881 if (expr->is_postfix() && !context()->IsEffect()) { |
| 3777 __ push(Immediate(Smi::FromInt(0))); | 3882 __ push(Immediate(Smi::FromInt(0))); |
| 3883 increment_stack_height(); |
| 3778 } | 3884 } |
| 3779 if (assign_type == NAMED_PROPERTY) { | 3885 if (assign_type == NAMED_PROPERTY) { |
| 3780 // Put the object both on the stack and in the accumulator. | 3886 // Put the object both on the stack and in the accumulator. |
| 3781 VisitForAccumulatorValue(prop->obj()); | 3887 VisitForAccumulatorValue(prop->obj()); |
| 3782 __ push(eax); | 3888 __ push(eax); |
| 3889 increment_stack_height(); |
| 3783 EmitNamedPropertyLoad(prop); | 3890 EmitNamedPropertyLoad(prop); |
| 3784 } else { | 3891 } else { |
| 3785 VisitForStackValue(prop->obj()); | 3892 VisitForStackValue(prop->obj()); |
| 3786 VisitForAccumulatorValue(prop->key()); | 3893 VisitForAccumulatorValue(prop->key()); |
| 3787 __ mov(edx, Operand(esp, 0)); | 3894 __ mov(edx, Operand(esp, 0)); |
| 3788 __ push(eax); | 3895 __ push(eax); |
| 3896 increment_stack_height(); |
| 3789 EmitKeyedPropertyLoad(prop); | 3897 EmitKeyedPropertyLoad(prop); |
| 3790 } | 3898 } |
| 3791 } | 3899 } |
| 3792 | 3900 |
| 3793 // We need a second deoptimization point after loading the value | 3901 // We need a second deoptimization point after loading the value |
| 3794 // in case evaluating the property load my have a side effect. | 3902 // in case evaluating the property load my have a side effect. |
| 3795 if (assign_type == VARIABLE) { | 3903 if (assign_type == VARIABLE) { |
| 3796 PrepareForBailout(expr->expression(), TOS_REG); | 3904 PrepareForBailout(expr->expression(), TOS_REG); |
| 3797 } else { | 3905 } else { |
| 3798 PrepareForBailoutForId(expr->CountId(), TOS_REG); | 3906 PrepareForBailoutForId(expr->CountId(), TOS_REG); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 3809 | 3917 |
| 3810 // Save result for postfix expressions. | 3918 // Save result for postfix expressions. |
| 3811 if (expr->is_postfix()) { | 3919 if (expr->is_postfix()) { |
| 3812 if (!context()->IsEffect()) { | 3920 if (!context()->IsEffect()) { |
| 3813 // Save the result on the stack. If we have a named or keyed property | 3921 // Save the result on the stack. If we have a named or keyed property |
| 3814 // we store the result under the receiver that is currently on top | 3922 // we store the result under the receiver that is currently on top |
| 3815 // of the stack. | 3923 // of the stack. |
| 3816 switch (assign_type) { | 3924 switch (assign_type) { |
| 3817 case VARIABLE: | 3925 case VARIABLE: |
| 3818 __ push(eax); | 3926 __ push(eax); |
| 3927 increment_stack_height(); |
| 3819 break; | 3928 break; |
| 3820 case NAMED_PROPERTY: | 3929 case NAMED_PROPERTY: |
| 3821 __ mov(Operand(esp, kPointerSize), eax); | 3930 __ mov(Operand(esp, kPointerSize), eax); |
| 3822 break; | 3931 break; |
| 3823 case KEYED_PROPERTY: | 3932 case KEYED_PROPERTY: |
| 3824 __ mov(Operand(esp, 2 * kPointerSize), eax); | 3933 __ mov(Operand(esp, 2 * kPointerSize), eax); |
| 3825 break; | 3934 break; |
| 3826 } | 3935 } |
| 3827 } | 3936 } |
| 3828 } | 3937 } |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3882 // Perform the assignment as if via '='. | 3991 // Perform the assignment as if via '='. |
| 3883 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), | 3992 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
| 3884 Token::ASSIGN); | 3993 Token::ASSIGN); |
| 3885 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 3994 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 3886 context()->Plug(eax); | 3995 context()->Plug(eax); |
| 3887 } | 3996 } |
| 3888 break; | 3997 break; |
| 3889 case NAMED_PROPERTY: { | 3998 case NAMED_PROPERTY: { |
| 3890 __ mov(ecx, prop->key()->AsLiteral()->handle()); | 3999 __ mov(ecx, prop->key()->AsLiteral()->handle()); |
| 3891 __ pop(edx); | 4000 __ pop(edx); |
| 4001 decrement_stack_height(); |
| 3892 Handle<Code> ic = is_strict_mode() | 4002 Handle<Code> ic = is_strict_mode() |
| 3893 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 4003 ? isolate()->builtins()->StoreIC_Initialize_Strict() |
| 3894 : isolate()->builtins()->StoreIC_Initialize(); | 4004 : isolate()->builtins()->StoreIC_Initialize(); |
| 3895 __ call(ic, RelocInfo::CODE_TARGET, expr->id()); | 4005 __ call(ic, RelocInfo::CODE_TARGET, expr->id()); |
| 3896 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 4006 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 3897 if (expr->is_postfix()) { | 4007 if (expr->is_postfix()) { |
| 3898 if (!context()->IsEffect()) { | 4008 if (!context()->IsEffect()) { |
| 3899 context()->PlugTOS(); | 4009 context()->PlugTOS(); |
| 3900 } | 4010 } |
| 3901 } else { | 4011 } else { |
| 3902 context()->Plug(eax); | 4012 context()->Plug(eax); |
| 3903 } | 4013 } |
| 3904 break; | 4014 break; |
| 3905 } | 4015 } |
| 3906 case KEYED_PROPERTY: { | 4016 case KEYED_PROPERTY: { |
| 3907 __ pop(ecx); | 4017 __ pop(ecx); |
| 3908 __ pop(edx); | 4018 __ pop(edx); |
| 4019 decrement_stack_height(); |
| 4020 decrement_stack_height(); |
| 3909 Handle<Code> ic = is_strict_mode() | 4021 Handle<Code> ic = is_strict_mode() |
| 3910 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() | 4022 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() |
| 3911 : isolate()->builtins()->KeyedStoreIC_Initialize(); | 4023 : isolate()->builtins()->KeyedStoreIC_Initialize(); |
| 3912 __ call(ic, RelocInfo::CODE_TARGET, expr->id()); | 4024 __ call(ic, RelocInfo::CODE_TARGET, expr->id()); |
| 3913 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 4025 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 3914 if (expr->is_postfix()) { | 4026 if (expr->is_postfix()) { |
| 3915 // Result is on the stack | 4027 // Result is on the stack |
| 3916 if (!context()->IsEffect()) { | 4028 if (!context()->IsEffect()) { |
| 3917 context()->PlugTOS(); | 4029 context()->PlugTOS(); |
| 3918 } | 4030 } |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4056 context()->Plug(if_true, if_false); | 4168 context()->Plug(if_true, if_false); |
| 4057 return; | 4169 return; |
| 4058 } | 4170 } |
| 4059 | 4171 |
| 4060 Token::Value op = expr->op(); | 4172 Token::Value op = expr->op(); |
| 4061 VisitForStackValue(expr->left()); | 4173 VisitForStackValue(expr->left()); |
| 4062 switch (expr->op()) { | 4174 switch (expr->op()) { |
| 4063 case Token::IN: | 4175 case Token::IN: |
| 4064 VisitForStackValue(expr->right()); | 4176 VisitForStackValue(expr->right()); |
| 4065 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION); | 4177 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION); |
| 4178 decrement_stack_height(2); |
| 4066 PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); | 4179 PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); |
| 4067 __ cmp(eax, isolate()->factory()->true_value()); | 4180 __ cmp(eax, isolate()->factory()->true_value()); |
| 4068 Split(equal, if_true, if_false, fall_through); | 4181 Split(equal, if_true, if_false, fall_through); |
| 4069 break; | 4182 break; |
| 4070 | 4183 |
| 4071 case Token::INSTANCEOF: { | 4184 case Token::INSTANCEOF: { |
| 4072 VisitForStackValue(expr->right()); | 4185 VisitForStackValue(expr->right()); |
| 4073 InstanceofStub stub(InstanceofStub::kNoFlags); | 4186 InstanceofStub stub(InstanceofStub::kNoFlags); |
| 4074 __ CallStub(&stub); | 4187 __ CallStub(&stub); |
| 4188 decrement_stack_height(2); |
| 4075 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); | 4189 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); |
| 4076 __ test(eax, Operand(eax)); | 4190 __ test(eax, Operand(eax)); |
| 4077 // The stub returns 0 for true. | 4191 // The stub returns 0 for true. |
| 4078 Split(zero, if_true, if_false, fall_through); | 4192 Split(zero, if_true, if_false, fall_through); |
| 4079 break; | 4193 break; |
| 4080 } | 4194 } |
| 4081 | 4195 |
| 4082 default: { | 4196 default: { |
| 4083 VisitForAccumulatorValue(expr->right()); | 4197 VisitForAccumulatorValue(expr->right()); |
| 4084 Condition cc = no_condition; | 4198 Condition cc = no_condition; |
| (...skipping 24 matching lines...) Expand all Loading... |
| 4109 break; | 4223 break; |
| 4110 case Token::GTE: | 4224 case Token::GTE: |
| 4111 cc = greater_equal; | 4225 cc = greater_equal; |
| 4112 __ pop(edx); | 4226 __ pop(edx); |
| 4113 break; | 4227 break; |
| 4114 case Token::IN: | 4228 case Token::IN: |
| 4115 case Token::INSTANCEOF: | 4229 case Token::INSTANCEOF: |
| 4116 default: | 4230 default: |
| 4117 UNREACHABLE(); | 4231 UNREACHABLE(); |
| 4118 } | 4232 } |
| 4233 decrement_stack_height(); |
| 4119 | 4234 |
| 4120 bool inline_smi_code = ShouldInlineSmiCase(op); | 4235 bool inline_smi_code = ShouldInlineSmiCase(op); |
| 4121 JumpPatchSite patch_site(masm_); | 4236 JumpPatchSite patch_site(masm_); |
| 4122 if (inline_smi_code) { | 4237 if (inline_smi_code) { |
| 4123 Label slow_case; | 4238 Label slow_case; |
| 4124 __ mov(ecx, Operand(edx)); | 4239 __ mov(ecx, Operand(edx)); |
| 4125 __ or_(ecx, Operand(eax)); | 4240 __ or_(ecx, Operand(eax)); |
| 4126 patch_site.EmitJumpIfNotSmi(ecx, &slow_case, Label::kNear); | 4241 patch_site.EmitJumpIfNotSmi(ecx, &slow_case, Label::kNear); |
| 4127 __ cmp(edx, Operand(eax)); | 4242 __ cmp(edx, Operand(eax)); |
| 4128 Split(cc, if_true, if_false, NULL); | 4243 Split(cc, if_true, if_false, NULL); |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4249 __ add(Operand(edx), Immediate(masm_->CodeObject())); | 4364 __ add(Operand(edx), Immediate(masm_->CodeObject())); |
| 4250 __ jmp(Operand(edx)); | 4365 __ jmp(Operand(edx)); |
| 4251 } | 4366 } |
| 4252 | 4367 |
| 4253 | 4368 |
| 4254 #undef __ | 4369 #undef __ |
| 4255 | 4370 |
| 4256 } } // namespace v8::internal | 4371 } } // namespace v8::internal |
| 4257 | 4372 |
| 4258 #endif // V8_TARGET_ARCH_IA32 | 4373 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |