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 |