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 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
122 #endif | 122 #endif |
123 | 123 |
124 __ push(ebp); // Caller's frame pointer. | 124 __ push(ebp); // Caller's frame pointer. |
125 __ mov(ebp, esp); | 125 __ mov(ebp, esp); |
126 __ push(esi); // Callee's context. | 126 __ push(esi); // Callee's context. |
127 __ push(edi); // Callee's JS Function. | 127 __ push(edi); // Callee's JS Function. |
128 | 128 |
129 { Comment cmnt(masm_, "[ Allocate locals"); | 129 { Comment cmnt(masm_, "[ Allocate locals"); |
130 int locals_count = scope()->num_stack_slots(); | 130 int locals_count = scope()->num_stack_slots(); |
131 if (locals_count == 1) { | 131 if (locals_count == 1) { |
132 __ push(Immediate(Factory::undefined_value())); | 132 __ push(Immediate(isolate()->factory()->undefined_value())); |
133 } else if (locals_count > 1) { | 133 } else if (locals_count > 1) { |
134 __ mov(eax, Immediate(Factory::undefined_value())); | 134 __ mov(eax, Immediate(isolate()->factory()->undefined_value())); |
135 for (int i = 0; i < locals_count; i++) { | 135 for (int i = 0; i < locals_count; i++) { |
136 __ push(eax); | 136 __ push(eax); |
137 } | 137 } |
138 } | 138 } |
139 } | 139 } |
140 | 140 |
141 bool function_in_register = true; | 141 bool function_in_register = true; |
142 | 142 |
143 // Possibly allocate a local context. | 143 // Possibly allocate a local context. |
144 int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; | 144 int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
245 { Comment cmnt(masm_, "[ Body"); | 245 { Comment cmnt(masm_, "[ Body"); |
246 ASSERT(loop_depth() == 0); | 246 ASSERT(loop_depth() == 0); |
247 VisitStatements(function()->body()); | 247 VisitStatements(function()->body()); |
248 ASSERT(loop_depth() == 0); | 248 ASSERT(loop_depth() == 0); |
249 } | 249 } |
250 } | 250 } |
251 | 251 |
252 // Always emit a 'return undefined' in case control fell off the end of | 252 // Always emit a 'return undefined' in case control fell off the end of |
253 // the body. | 253 // the body. |
254 { Comment cmnt(masm_, "[ return <undefined>;"); | 254 { Comment cmnt(masm_, "[ return <undefined>;"); |
255 __ mov(eax, Factory::undefined_value()); | 255 __ mov(eax, isolate()->factory()->undefined_value()); |
256 EmitReturnSequence(); | 256 EmitReturnSequence(); |
257 } | 257 } |
258 } | 258 } |
259 | 259 |
260 | 260 |
261 void FullCodeGenerator::ClearAccumulator() { | 261 void FullCodeGenerator::ClearAccumulator() { |
262 __ Set(eax, Immediate(Smi::FromInt(0))); | 262 __ Set(eax, Immediate(Smi::FromInt(0))); |
263 } | 263 } |
264 | 264 |
265 | 265 |
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
460 ASSERT(materialize_true == materialize_false); | 460 ASSERT(materialize_true == materialize_false); |
461 __ bind(materialize_true); | 461 __ bind(materialize_true); |
462 } | 462 } |
463 | 463 |
464 | 464 |
465 void FullCodeGenerator::AccumulatorValueContext::Plug( | 465 void FullCodeGenerator::AccumulatorValueContext::Plug( |
466 Label* materialize_true, | 466 Label* materialize_true, |
467 Label* materialize_false) const { | 467 Label* materialize_false) const { |
468 NearLabel done; | 468 NearLabel done; |
469 __ bind(materialize_true); | 469 __ bind(materialize_true); |
470 __ mov(result_register(), Factory::true_value()); | 470 __ mov(result_register(), isolate()->factory()->true_value()); |
471 __ jmp(&done); | 471 __ jmp(&done); |
472 __ bind(materialize_false); | 472 __ bind(materialize_false); |
473 __ mov(result_register(), Factory::false_value()); | 473 __ mov(result_register(), isolate()->factory()->false_value()); |
474 __ bind(&done); | 474 __ bind(&done); |
475 } | 475 } |
476 | 476 |
477 | 477 |
478 void FullCodeGenerator::StackValueContext::Plug( | 478 void FullCodeGenerator::StackValueContext::Plug( |
479 Label* materialize_true, | 479 Label* materialize_true, |
480 Label* materialize_false) const { | 480 Label* materialize_false) const { |
481 NearLabel done; | 481 NearLabel done; |
482 __ bind(materialize_true); | 482 __ bind(materialize_true); |
483 __ push(Immediate(Factory::true_value())); | 483 __ push(Immediate(isolate()->factory()->true_value())); |
484 __ jmp(&done); | 484 __ jmp(&done); |
485 __ bind(materialize_false); | 485 __ bind(materialize_false); |
486 __ push(Immediate(Factory::false_value())); | 486 __ push(Immediate(isolate()->factory()->false_value())); |
487 __ bind(&done); | 487 __ bind(&done); |
488 } | 488 } |
489 | 489 |
490 | 490 |
491 void FullCodeGenerator::TestContext::Plug(Label* materialize_true, | 491 void FullCodeGenerator::TestContext::Plug(Label* materialize_true, |
492 Label* materialize_false) const { | 492 Label* materialize_false) const { |
493 ASSERT(materialize_true == true_label_); | 493 ASSERT(materialize_true == true_label_); |
494 ASSERT(materialize_false == false_label_); | 494 ASSERT(materialize_false == false_label_); |
495 } | 495 } |
496 | 496 |
497 | 497 |
498 void FullCodeGenerator::EffectContext::Plug(bool flag) const { | 498 void FullCodeGenerator::EffectContext::Plug(bool flag) const { |
499 } | 499 } |
500 | 500 |
501 | 501 |
502 void FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const { | 502 void FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const { |
503 Handle<Object> value = | 503 Handle<Object> value = flag |
504 flag ? Factory::true_value() : Factory::false_value(); | 504 ? isolate()->factory()->true_value() |
| 505 : isolate()->factory()->false_value(); |
505 __ mov(result_register(), value); | 506 __ mov(result_register(), value); |
506 } | 507 } |
507 | 508 |
508 | 509 |
509 void FullCodeGenerator::StackValueContext::Plug(bool flag) const { | 510 void FullCodeGenerator::StackValueContext::Plug(bool flag) const { |
510 Handle<Object> value = | 511 Handle<Object> value = flag |
511 flag ? Factory::true_value() : Factory::false_value(); | 512 ? isolate()->factory()->true_value() |
| 513 : isolate()->factory()->false_value(); |
512 __ push(Immediate(value)); | 514 __ push(Immediate(value)); |
513 } | 515 } |
514 | 516 |
515 | 517 |
516 void FullCodeGenerator::TestContext::Plug(bool flag) const { | 518 void FullCodeGenerator::TestContext::Plug(bool flag) const { |
517 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, | 519 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, |
518 true, | 520 true, |
519 true_label_, | 521 true_label_, |
520 false_label_); | 522 false_label_); |
521 if (flag) { | 523 if (flag) { |
522 if (true_label_ != fall_through_) __ jmp(true_label_); | 524 if (true_label_ != fall_through_) __ jmp(true_label_); |
523 } else { | 525 } else { |
524 if (false_label_ != fall_through_) __ jmp(false_label_); | 526 if (false_label_ != fall_through_) __ jmp(false_label_); |
525 } | 527 } |
526 } | 528 } |
527 | 529 |
528 | 530 |
529 void FullCodeGenerator::DoTest(Label* if_true, | 531 void FullCodeGenerator::DoTest(Label* if_true, |
530 Label* if_false, | 532 Label* if_false, |
531 Label* fall_through) { | 533 Label* fall_through) { |
532 // Emit the inlined tests assumed by the stub. | 534 // Emit the inlined tests assumed by the stub. |
533 __ cmp(result_register(), Factory::undefined_value()); | 535 __ cmp(result_register(), isolate()->factory()->undefined_value()); |
534 __ j(equal, if_false); | 536 __ j(equal, if_false); |
535 __ cmp(result_register(), Factory::true_value()); | 537 __ cmp(result_register(), isolate()->factory()->true_value()); |
536 __ j(equal, if_true); | 538 __ j(equal, if_true); |
537 __ cmp(result_register(), Factory::false_value()); | 539 __ cmp(result_register(), isolate()->factory()->false_value()); |
538 __ j(equal, if_false); | 540 __ j(equal, if_false); |
539 STATIC_ASSERT(kSmiTag == 0); | 541 STATIC_ASSERT(kSmiTag == 0); |
540 __ test(result_register(), Operand(result_register())); | 542 __ test(result_register(), Operand(result_register())); |
541 __ j(zero, if_false); | 543 __ j(zero, if_false); |
542 __ test(result_register(), Immediate(kSmiTagMask)); | 544 __ test(result_register(), Immediate(kSmiTagMask)); |
543 __ j(zero, if_true); | 545 __ j(zero, if_true); |
544 | 546 |
545 // Call the ToBoolean stub for all other cases. | 547 // Call the ToBoolean stub for all other cases. |
546 ToBooleanStub stub; | 548 ToBooleanStub stub; |
547 __ push(result_register()); | 549 __ push(result_register()); |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
622 NearLabel skip; | 624 NearLabel skip; |
623 if (should_normalize) __ jmp(&skip); | 625 if (should_normalize) __ jmp(&skip); |
624 | 626 |
625 ForwardBailoutStack* current = forward_bailout_stack_; | 627 ForwardBailoutStack* current = forward_bailout_stack_; |
626 while (current != NULL) { | 628 while (current != NULL) { |
627 PrepareForBailout(current->expr(), state); | 629 PrepareForBailout(current->expr(), state); |
628 current = current->parent(); | 630 current = current->parent(); |
629 } | 631 } |
630 | 632 |
631 if (should_normalize) { | 633 if (should_normalize) { |
632 __ cmp(eax, Factory::true_value()); | 634 __ cmp(eax, isolate()->factory()->true_value()); |
633 Split(equal, if_true, if_false, NULL); | 635 Split(equal, if_true, if_false, NULL); |
634 __ bind(&skip); | 636 __ bind(&skip); |
635 } | 637 } |
636 } | 638 } |
637 | 639 |
638 | 640 |
639 void FullCodeGenerator::EmitDeclaration(Variable* variable, | 641 void FullCodeGenerator::EmitDeclaration(Variable* variable, |
640 Variable::Mode mode, | 642 Variable::Mode mode, |
641 FunctionLiteral* function) { | 643 FunctionLiteral* function) { |
642 Comment cmnt(masm_, "[ Declaration"); | 644 Comment cmnt(masm_, "[ Declaration"); |
643 ASSERT(variable != NULL); // Must have been resolved. | 645 ASSERT(variable != NULL); // Must have been resolved. |
644 Slot* slot = variable->AsSlot(); | 646 Slot* slot = variable->AsSlot(); |
645 Property* prop = variable->AsProperty(); | 647 Property* prop = variable->AsProperty(); |
646 | 648 |
647 if (slot != NULL) { | 649 if (slot != NULL) { |
648 switch (slot->type()) { | 650 switch (slot->type()) { |
649 case Slot::PARAMETER: | 651 case Slot::PARAMETER: |
650 case Slot::LOCAL: | 652 case Slot::LOCAL: |
651 if (mode == Variable::CONST) { | 653 if (mode == Variable::CONST) { |
652 __ mov(Operand(ebp, SlotOffset(slot)), | 654 __ mov(Operand(ebp, SlotOffset(slot)), |
653 Immediate(Factory::the_hole_value())); | 655 Immediate(isolate()->factory()->the_hole_value())); |
654 } else if (function != NULL) { | 656 } else if (function != NULL) { |
655 VisitForAccumulatorValue(function); | 657 VisitForAccumulatorValue(function); |
656 __ mov(Operand(ebp, SlotOffset(slot)), result_register()); | 658 __ mov(Operand(ebp, SlotOffset(slot)), result_register()); |
657 } | 659 } |
658 break; | 660 break; |
659 | 661 |
660 case Slot::CONTEXT: | 662 case Slot::CONTEXT: |
661 // We bypass the general EmitSlotSearch because we know more about | 663 // We bypass the general EmitSlotSearch because we know more about |
662 // this specific context. | 664 // this specific context. |
663 | 665 |
664 // The variable in the decl always resides in the current function | 666 // The variable in the decl always resides in the current function |
665 // context. | 667 // context. |
666 ASSERT_EQ(0, scope()->ContextChainLength(variable->scope())); | 668 ASSERT_EQ(0, scope()->ContextChainLength(variable->scope())); |
667 if (FLAG_debug_code) { | 669 if (FLAG_debug_code) { |
668 // Check that we're not inside a 'with'. | 670 // Check that we're not inside a 'with'. |
669 __ mov(ebx, ContextOperand(esi, Context::FCONTEXT_INDEX)); | 671 __ mov(ebx, ContextOperand(esi, Context::FCONTEXT_INDEX)); |
670 __ cmp(ebx, Operand(esi)); | 672 __ cmp(ebx, Operand(esi)); |
671 __ Check(equal, "Unexpected declaration in current context."); | 673 __ Check(equal, "Unexpected declaration in current context."); |
672 } | 674 } |
673 if (mode == Variable::CONST) { | 675 if (mode == Variable::CONST) { |
674 __ mov(ContextOperand(esi, slot->index()), | 676 __ mov(ContextOperand(esi, slot->index()), |
675 Immediate(Factory::the_hole_value())); | 677 Immediate(isolate()->factory()->the_hole_value())); |
676 // No write barrier since the hole value is in old space. | 678 // No write barrier since the hole value is in old space. |
677 } else if (function != NULL) { | 679 } else if (function != NULL) { |
678 VisitForAccumulatorValue(function); | 680 VisitForAccumulatorValue(function); |
679 __ mov(ContextOperand(esi, slot->index()), result_register()); | 681 __ mov(ContextOperand(esi, slot->index()), result_register()); |
680 int offset = Context::SlotOffset(slot->index()); | 682 int offset = Context::SlotOffset(slot->index()); |
681 __ mov(ebx, esi); | 683 __ mov(ebx, esi); |
682 __ RecordWrite(ebx, offset, result_register(), ecx); | 684 __ RecordWrite(ebx, offset, result_register(), ecx); |
683 } | 685 } |
684 break; | 686 break; |
685 | 687 |
686 case Slot::LOOKUP: { | 688 case Slot::LOOKUP: { |
687 __ push(esi); | 689 __ push(esi); |
688 __ push(Immediate(variable->name())); | 690 __ push(Immediate(variable->name())); |
689 // Declaration nodes are always introduced in one of two modes. | 691 // Declaration nodes are always introduced in one of two modes. |
690 ASSERT(mode == Variable::VAR || mode == Variable::CONST); | 692 ASSERT(mode == Variable::VAR || mode == Variable::CONST); |
691 PropertyAttributes attr = (mode == Variable::VAR) ? NONE : READ_ONLY; | 693 PropertyAttributes attr = (mode == Variable::VAR) ? NONE : READ_ONLY; |
692 __ push(Immediate(Smi::FromInt(attr))); | 694 __ push(Immediate(Smi::FromInt(attr))); |
693 // Push initial value, if any. | 695 // Push initial value, if any. |
694 // Note: For variables we must not push an initial value (such as | 696 // Note: For variables we must not push an initial value (such as |
695 // 'undefined') because we may have a (legal) redeclaration and we | 697 // 'undefined') because we may have a (legal) redeclaration and we |
696 // must not destroy the current value. | 698 // must not destroy the current value. |
697 if (mode == Variable::CONST) { | 699 if (mode == Variable::CONST) { |
698 __ push(Immediate(Factory::the_hole_value())); | 700 __ push(Immediate(isolate()->factory()->the_hole_value())); |
699 } else if (function != NULL) { | 701 } else if (function != NULL) { |
700 VisitForStackValue(function); | 702 VisitForStackValue(function); |
701 } else { | 703 } else { |
702 __ push(Immediate(Smi::FromInt(0))); // No initial value! | 704 __ push(Immediate(Smi::FromInt(0))); // No initial value! |
703 } | 705 } |
704 __ CallRuntime(Runtime::kDeclareContextSlot, 4); | 706 __ CallRuntime(Runtime::kDeclareContextSlot, 4); |
705 break; | 707 break; |
706 } | 708 } |
707 } | 709 } |
708 | 710 |
709 } else if (prop != NULL) { | 711 } else if (prop != NULL) { |
710 if (function != NULL || mode == Variable::CONST) { | 712 if (function != NULL || mode == Variable::CONST) { |
711 // We are declaring a function or constant that rewrites to a | 713 // We are declaring a function or constant that rewrites to a |
712 // property. Use (keyed) IC to set the initial value. We cannot | 714 // property. Use (keyed) IC to set the initial value. We cannot |
713 // visit the rewrite because it's shared and we risk recording | 715 // visit the rewrite because it's shared and we risk recording |
714 // duplicate AST IDs for bailouts from optimized code. | 716 // duplicate AST IDs for bailouts from optimized code. |
715 ASSERT(prop->obj()->AsVariableProxy() != NULL); | 717 ASSERT(prop->obj()->AsVariableProxy() != NULL); |
716 { AccumulatorValueContext for_object(this); | 718 { AccumulatorValueContext for_object(this); |
717 EmitVariableLoad(prop->obj()->AsVariableProxy()->var()); | 719 EmitVariableLoad(prop->obj()->AsVariableProxy()->var()); |
718 } | 720 } |
719 | 721 |
720 if (function != NULL) { | 722 if (function != NULL) { |
721 __ push(eax); | 723 __ push(eax); |
722 VisitForAccumulatorValue(function); | 724 VisitForAccumulatorValue(function); |
723 __ pop(edx); | 725 __ pop(edx); |
724 } else { | 726 } else { |
725 __ mov(edx, eax); | 727 __ mov(edx, eax); |
726 __ mov(eax, Factory::the_hole_value()); | 728 __ mov(eax, isolate()->factory()->the_hole_value()); |
727 } | 729 } |
728 ASSERT(prop->key()->AsLiteral() != NULL && | 730 ASSERT(prop->key()->AsLiteral() != NULL && |
729 prop->key()->AsLiteral()->handle()->IsSmi()); | 731 prop->key()->AsLiteral()->handle()->IsSmi()); |
730 __ Set(ecx, Immediate(prop->key()->AsLiteral()->handle())); | 732 __ Set(ecx, Immediate(prop->key()->AsLiteral()->handle())); |
731 | 733 |
732 Handle<Code> ic(Builtins::builtin( | 734 Handle<Code> ic(isolate()->builtins()->builtin(is_strict_mode() |
733 is_strict_mode() ? Builtins::KeyedStoreIC_Initialize_Strict | 735 ? Builtins::KeyedStoreIC_Initialize_Strict |
734 : Builtins::KeyedStoreIC_Initialize)); | 736 : Builtins::KeyedStoreIC_Initialize)); |
735 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 737 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
736 } | 738 } |
737 } | 739 } |
738 } | 740 } |
739 | 741 |
740 | 742 |
741 void FullCodeGenerator::VisitDeclaration(Declaration* decl) { | 743 void FullCodeGenerator::VisitDeclaration(Declaration* decl) { |
742 EmitDeclaration(decl->proxy()->var(), decl->mode(), decl->fun()); | 744 EmitDeclaration(decl->proxy()->var(), decl->mode(), decl->fun()); |
743 } | 745 } |
744 | 746 |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
841 SetStatementPosition(stmt); | 843 SetStatementPosition(stmt); |
842 | 844 |
843 Label loop, exit; | 845 Label loop, exit; |
844 ForIn loop_statement(this, stmt); | 846 ForIn loop_statement(this, stmt); |
845 increment_loop_depth(); | 847 increment_loop_depth(); |
846 | 848 |
847 // Get the object to enumerate over. Both SpiderMonkey and JSC | 849 // Get the object to enumerate over. Both SpiderMonkey and JSC |
848 // ignore null and undefined in contrast to the specification; see | 850 // ignore null and undefined in contrast to the specification; see |
849 // ECMA-262 section 12.6.4. | 851 // ECMA-262 section 12.6.4. |
850 VisitForAccumulatorValue(stmt->enumerable()); | 852 VisitForAccumulatorValue(stmt->enumerable()); |
851 __ cmp(eax, Factory::undefined_value()); | 853 __ cmp(eax, isolate()->factory()->undefined_value()); |
852 __ j(equal, &exit); | 854 __ j(equal, &exit); |
853 __ cmp(eax, Factory::null_value()); | 855 __ cmp(eax, isolate()->factory()->null_value()); |
854 __ j(equal, &exit); | 856 __ j(equal, &exit); |
855 | 857 |
856 // Convert the object to a JS object. | 858 // Convert the object to a JS object. |
857 NearLabel convert, done_convert; | 859 NearLabel convert, done_convert; |
858 __ test(eax, Immediate(kSmiTagMask)); | 860 __ test(eax, Immediate(kSmiTagMask)); |
859 __ j(zero, &convert); | 861 __ j(zero, &convert); |
860 __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, ecx); | 862 __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, ecx); |
861 __ j(above_equal, &done_convert); | 863 __ j(above_equal, &done_convert); |
862 __ bind(&convert); | 864 __ bind(&convert); |
863 __ push(eax); | 865 __ push(eax); |
864 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); | 866 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); |
865 __ bind(&done_convert); | 867 __ bind(&done_convert); |
866 __ push(eax); | 868 __ push(eax); |
867 | 869 |
868 // Check cache validity in generated code. This is a fast case for | 870 // Check cache validity in generated code. This is a fast case for |
869 // the JSObject::IsSimpleEnum cache validity checks. If we cannot | 871 // the JSObject::IsSimpleEnum cache validity checks. If we cannot |
870 // guarantee cache validity, call the runtime system to check cache | 872 // guarantee cache validity, call the runtime system to check cache |
871 // validity or get the property names in a fixed array. | 873 // validity or get the property names in a fixed array. |
872 Label next, call_runtime; | 874 Label next, call_runtime; |
873 __ mov(ecx, eax); | 875 __ mov(ecx, eax); |
874 __ bind(&next); | 876 __ bind(&next); |
875 | 877 |
876 // Check that there are no elements. Register ecx contains the | 878 // Check that there are no elements. Register ecx contains the |
877 // current JS object we've reached through the prototype chain. | 879 // current JS object we've reached through the prototype chain. |
878 __ cmp(FieldOperand(ecx, JSObject::kElementsOffset), | 880 __ cmp(FieldOperand(ecx, JSObject::kElementsOffset), |
879 Factory::empty_fixed_array()); | 881 isolate()->factory()->empty_fixed_array()); |
880 __ j(not_equal, &call_runtime); | 882 __ j(not_equal, &call_runtime); |
881 | 883 |
882 // Check that instance descriptors are not empty so that we can | 884 // Check that instance descriptors are not empty so that we can |
883 // check for an enum cache. Leave the map in ebx for the subsequent | 885 // check for an enum cache. Leave the map in ebx for the subsequent |
884 // prototype load. | 886 // prototype load. |
885 __ mov(ebx, FieldOperand(ecx, HeapObject::kMapOffset)); | 887 __ mov(ebx, FieldOperand(ecx, HeapObject::kMapOffset)); |
886 __ mov(edx, FieldOperand(ebx, Map::kInstanceDescriptorsOffset)); | 888 __ mov(edx, FieldOperand(ebx, Map::kInstanceDescriptorsOffset)); |
887 __ cmp(edx, Factory::empty_descriptor_array()); | 889 __ cmp(edx, isolate()->factory()->empty_descriptor_array()); |
888 __ j(equal, &call_runtime); | 890 __ j(equal, &call_runtime); |
889 | 891 |
890 // Check that there is an enum cache in the non-empty instance | 892 // Check that there is an enum cache in the non-empty instance |
891 // descriptors (edx). This is the case if the next enumeration | 893 // descriptors (edx). This is the case if the next enumeration |
892 // index field does not contain a smi. | 894 // index field does not contain a smi. |
893 __ mov(edx, FieldOperand(edx, DescriptorArray::kEnumerationIndexOffset)); | 895 __ mov(edx, FieldOperand(edx, DescriptorArray::kEnumerationIndexOffset)); |
894 __ test(edx, Immediate(kSmiTagMask)); | 896 __ test(edx, Immediate(kSmiTagMask)); |
895 __ j(zero, &call_runtime); | 897 __ j(zero, &call_runtime); |
896 | 898 |
897 // For all objects but the receiver, check that the cache is empty. | 899 // For all objects but the receiver, check that the cache is empty. |
898 NearLabel check_prototype; | 900 NearLabel check_prototype; |
899 __ cmp(ecx, Operand(eax)); | 901 __ cmp(ecx, Operand(eax)); |
900 __ j(equal, &check_prototype); | 902 __ j(equal, &check_prototype); |
901 __ mov(edx, FieldOperand(edx, DescriptorArray::kEnumCacheBridgeCacheOffset)); | 903 __ mov(edx, FieldOperand(edx, DescriptorArray::kEnumCacheBridgeCacheOffset)); |
902 __ cmp(edx, Factory::empty_fixed_array()); | 904 __ cmp(edx, isolate()->factory()->empty_fixed_array()); |
903 __ j(not_equal, &call_runtime); | 905 __ j(not_equal, &call_runtime); |
904 | 906 |
905 // Load the prototype from the map and loop if non-null. | 907 // Load the prototype from the map and loop if non-null. |
906 __ bind(&check_prototype); | 908 __ bind(&check_prototype); |
907 __ mov(ecx, FieldOperand(ebx, Map::kPrototypeOffset)); | 909 __ mov(ecx, FieldOperand(ebx, Map::kPrototypeOffset)); |
908 __ cmp(ecx, Factory::null_value()); | 910 __ cmp(ecx, isolate()->factory()->null_value()); |
909 __ j(not_equal, &next); | 911 __ j(not_equal, &next); |
910 | 912 |
911 // The enum cache is valid. Load the map of the object being | 913 // The enum cache is valid. Load the map of the object being |
912 // iterated over and use the cache for the iteration. | 914 // iterated over and use the cache for the iteration. |
913 NearLabel use_cache; | 915 NearLabel use_cache; |
914 __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset)); | 916 __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset)); |
915 __ jmp(&use_cache); | 917 __ jmp(&use_cache); |
916 | 918 |
917 // Get the set of properties to enumerate. | 919 // Get the set of properties to enumerate. |
918 __ bind(&call_runtime); | 920 __ bind(&call_runtime); |
919 __ push(eax); // Duplicate the enumerable object on the stack. | 921 __ push(eax); // Duplicate the enumerable object on the stack. |
920 __ CallRuntime(Runtime::kGetPropertyNamesFast, 1); | 922 __ CallRuntime(Runtime::kGetPropertyNamesFast, 1); |
921 | 923 |
922 // If we got a map from the runtime call, we can do a fast | 924 // If we got a map from the runtime call, we can do a fast |
923 // modification check. Otherwise, we got a fixed array, and we have | 925 // modification check. Otherwise, we got a fixed array, and we have |
924 // to do a slow check. | 926 // to do a slow check. |
925 NearLabel fixed_array; | 927 NearLabel fixed_array; |
926 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), Factory::meta_map()); | 928 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), |
| 929 isolate()->factory()->meta_map()); |
927 __ j(not_equal, &fixed_array); | 930 __ j(not_equal, &fixed_array); |
928 | 931 |
929 // We got a map in register eax. Get the enumeration cache from it. | 932 // We got a map in register eax. Get the enumeration cache from it. |
930 __ bind(&use_cache); | 933 __ bind(&use_cache); |
931 __ mov(ecx, FieldOperand(eax, Map::kInstanceDescriptorsOffset)); | 934 __ mov(ecx, FieldOperand(eax, Map::kInstanceDescriptorsOffset)); |
932 __ mov(ecx, FieldOperand(ecx, DescriptorArray::kEnumerationIndexOffset)); | 935 __ mov(ecx, FieldOperand(ecx, DescriptorArray::kEnumerationIndexOffset)); |
933 __ mov(edx, FieldOperand(ecx, DescriptorArray::kEnumCacheBridgeCacheOffset)); | 936 __ mov(edx, FieldOperand(ecx, DescriptorArray::kEnumCacheBridgeCacheOffset)); |
934 | 937 |
935 // Setup the four remaining stack slots. | 938 // Setup the four remaining stack slots. |
936 __ push(eax); // Map. | 939 __ push(eax); // Map. |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1022 !pretenure && | 1025 !pretenure && |
1023 scope()->is_function_scope() && | 1026 scope()->is_function_scope() && |
1024 info->num_literals() == 0) { | 1027 info->num_literals() == 0) { |
1025 FastNewClosureStub stub(info->strict_mode() ? kStrictMode : kNonStrictMode); | 1028 FastNewClosureStub stub(info->strict_mode() ? kStrictMode : kNonStrictMode); |
1026 __ push(Immediate(info)); | 1029 __ push(Immediate(info)); |
1027 __ CallStub(&stub); | 1030 __ CallStub(&stub); |
1028 } else { | 1031 } else { |
1029 __ push(esi); | 1032 __ push(esi); |
1030 __ push(Immediate(info)); | 1033 __ push(Immediate(info)); |
1031 __ push(Immediate(pretenure | 1034 __ push(Immediate(pretenure |
1032 ? Factory::true_value() | 1035 ? isolate()->factory()->true_value() |
1033 : Factory::false_value())); | 1036 : isolate()->factory()->false_value())); |
1034 __ CallRuntime(Runtime::kNewClosure, 3); | 1037 __ CallRuntime(Runtime::kNewClosure, 3); |
1035 } | 1038 } |
1036 context()->Plug(eax); | 1039 context()->Plug(eax); |
1037 } | 1040 } |
1038 | 1041 |
1039 | 1042 |
1040 void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { | 1043 void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { |
1041 Comment cmnt(masm_, "[ VariableProxy"); | 1044 Comment cmnt(masm_, "[ VariableProxy"); |
1042 EmitVariableLoad(expr->var()); | 1045 EmitVariableLoad(expr->var()); |
1043 } | 1046 } |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1075 if (s != NULL && s->is_eval_scope()) { | 1078 if (s != NULL && s->is_eval_scope()) { |
1076 // Loop up the context chain. There is no frame effect so it is | 1079 // Loop up the context chain. There is no frame effect so it is |
1077 // safe to use raw labels here. | 1080 // safe to use raw labels here. |
1078 NearLabel next, fast; | 1081 NearLabel next, fast; |
1079 if (!context.is(temp)) { | 1082 if (!context.is(temp)) { |
1080 __ mov(temp, context); | 1083 __ mov(temp, context); |
1081 } | 1084 } |
1082 __ bind(&next); | 1085 __ bind(&next); |
1083 // Terminate at global context. | 1086 // Terminate at global context. |
1084 __ cmp(FieldOperand(temp, HeapObject::kMapOffset), | 1087 __ cmp(FieldOperand(temp, HeapObject::kMapOffset), |
1085 Immediate(Factory::global_context_map())); | 1088 Immediate(isolate()->factory()->global_context_map())); |
1086 __ j(equal, &fast); | 1089 __ j(equal, &fast); |
1087 // Check that extension is NULL. | 1090 // Check that extension is NULL. |
1088 __ cmp(ContextOperand(temp, Context::EXTENSION_INDEX), Immediate(0)); | 1091 __ cmp(ContextOperand(temp, Context::EXTENSION_INDEX), Immediate(0)); |
1089 __ j(not_equal, slow); | 1092 __ j(not_equal, slow); |
1090 // Load next context in chain. | 1093 // Load next context in chain. |
1091 __ mov(temp, ContextOperand(temp, Context::CLOSURE_INDEX)); | 1094 __ mov(temp, ContextOperand(temp, Context::CLOSURE_INDEX)); |
1092 __ mov(temp, FieldOperand(temp, JSFunction::kContextOffset)); | 1095 __ mov(temp, FieldOperand(temp, JSFunction::kContextOffset)); |
1093 __ jmp(&next); | 1096 __ jmp(&next); |
1094 __ bind(&fast); | 1097 __ bind(&fast); |
1095 } | 1098 } |
1096 | 1099 |
1097 // All extension objects were empty and it is safe to use a global | 1100 // All extension objects were empty and it is safe to use a global |
1098 // load IC call. | 1101 // load IC call. |
1099 __ mov(eax, GlobalObjectOperand()); | 1102 __ mov(eax, GlobalObjectOperand()); |
1100 __ mov(ecx, slot->var()->name()); | 1103 __ mov(ecx, slot->var()->name()); |
1101 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 1104 Handle<Code> ic(isolate()->builtins()->builtin( |
| 1105 Builtins::LoadIC_Initialize)); |
1102 RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF) | 1106 RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF) |
1103 ? RelocInfo::CODE_TARGET | 1107 ? RelocInfo::CODE_TARGET |
1104 : RelocInfo::CODE_TARGET_CONTEXT; | 1108 : RelocInfo::CODE_TARGET_CONTEXT; |
1105 EmitCallIC(ic, mode); | 1109 EmitCallIC(ic, mode); |
1106 } | 1110 } |
1107 | 1111 |
1108 | 1112 |
1109 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions( | 1113 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions( |
1110 Slot* slot, | 1114 Slot* slot, |
1111 Label* slow) { | 1115 Label* slow) { |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1152 EmitLoadGlobalSlotCheckExtensions(slot, typeof_state, slow); | 1156 EmitLoadGlobalSlotCheckExtensions(slot, typeof_state, slow); |
1153 __ jmp(done); | 1157 __ jmp(done); |
1154 } else if (slot->var()->mode() == Variable::DYNAMIC_LOCAL) { | 1158 } else if (slot->var()->mode() == Variable::DYNAMIC_LOCAL) { |
1155 Slot* potential_slot = slot->var()->local_if_not_shadowed()->AsSlot(); | 1159 Slot* potential_slot = slot->var()->local_if_not_shadowed()->AsSlot(); |
1156 Expression* rewrite = slot->var()->local_if_not_shadowed()->rewrite(); | 1160 Expression* rewrite = slot->var()->local_if_not_shadowed()->rewrite(); |
1157 if (potential_slot != NULL) { | 1161 if (potential_slot != NULL) { |
1158 // Generate fast case for locals that rewrite to slots. | 1162 // Generate fast case for locals that rewrite to slots. |
1159 __ mov(eax, | 1163 __ mov(eax, |
1160 ContextSlotOperandCheckExtensions(potential_slot, slow)); | 1164 ContextSlotOperandCheckExtensions(potential_slot, slow)); |
1161 if (potential_slot->var()->mode() == Variable::CONST) { | 1165 if (potential_slot->var()->mode() == Variable::CONST) { |
1162 __ cmp(eax, Factory::the_hole_value()); | 1166 __ cmp(eax, isolate()->factory()->the_hole_value()); |
1163 __ j(not_equal, done); | 1167 __ j(not_equal, done); |
1164 __ mov(eax, Factory::undefined_value()); | 1168 __ mov(eax, isolate()->factory()->undefined_value()); |
1165 } | 1169 } |
1166 __ jmp(done); | 1170 __ jmp(done); |
1167 } else if (rewrite != NULL) { | 1171 } else if (rewrite != NULL) { |
1168 // Generate fast case for calls of an argument function. | 1172 // Generate fast case for calls of an argument function. |
1169 Property* property = rewrite->AsProperty(); | 1173 Property* property = rewrite->AsProperty(); |
1170 if (property != NULL) { | 1174 if (property != NULL) { |
1171 VariableProxy* obj_proxy = property->obj()->AsVariableProxy(); | 1175 VariableProxy* obj_proxy = property->obj()->AsVariableProxy(); |
1172 Literal* key_literal = property->key()->AsLiteral(); | 1176 Literal* key_literal = property->key()->AsLiteral(); |
1173 if (obj_proxy != NULL && | 1177 if (obj_proxy != NULL && |
1174 key_literal != NULL && | 1178 key_literal != NULL && |
1175 obj_proxy->IsArguments() && | 1179 obj_proxy->IsArguments() && |
1176 key_literal->handle()->IsSmi()) { | 1180 key_literal->handle()->IsSmi()) { |
1177 // Load arguments object if there are no eval-introduced | 1181 // Load arguments object if there are no eval-introduced |
1178 // variables. Then load the argument from the arguments | 1182 // variables. Then load the argument from the arguments |
1179 // object using keyed load. | 1183 // object using keyed load. |
1180 __ mov(edx, | 1184 __ mov(edx, |
1181 ContextSlotOperandCheckExtensions(obj_proxy->var()->AsSlot(), | 1185 ContextSlotOperandCheckExtensions(obj_proxy->var()->AsSlot(), |
1182 slow)); | 1186 slow)); |
1183 __ mov(eax, Immediate(key_literal->handle())); | 1187 __ mov(eax, Immediate(key_literal->handle())); |
1184 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 1188 Handle<Code> ic(isolate()->builtins()->builtin( |
| 1189 Builtins::KeyedLoadIC_Initialize)); |
1185 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 1190 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
1186 __ jmp(done); | 1191 __ jmp(done); |
1187 } | 1192 } |
1188 } | 1193 } |
1189 } | 1194 } |
1190 } | 1195 } |
1191 } | 1196 } |
1192 | 1197 |
1193 | 1198 |
1194 void FullCodeGenerator::EmitVariableLoad(Variable* var) { | 1199 void FullCodeGenerator::EmitVariableLoad(Variable* var) { |
1195 // Four cases: non-this global variables, lookup slots, all other | 1200 // Four cases: non-this global variables, lookup slots, all other |
1196 // types of slots, and parameters that rewrite to explicit property | 1201 // types of slots, and parameters that rewrite to explicit property |
1197 // accesses on the arguments object. | 1202 // accesses on the arguments object. |
1198 Slot* slot = var->AsSlot(); | 1203 Slot* slot = var->AsSlot(); |
1199 Property* property = var->AsProperty(); | 1204 Property* property = var->AsProperty(); |
1200 | 1205 |
1201 if (var->is_global() && !var->is_this()) { | 1206 if (var->is_global() && !var->is_this()) { |
1202 Comment cmnt(masm_, "Global variable"); | 1207 Comment cmnt(masm_, "Global variable"); |
1203 // Use inline caching. Variable name is passed in ecx and the global | 1208 // Use inline caching. Variable name is passed in ecx and the global |
1204 // object on the stack. | 1209 // object on the stack. |
1205 __ mov(eax, GlobalObjectOperand()); | 1210 __ mov(eax, GlobalObjectOperand()); |
1206 __ mov(ecx, var->name()); | 1211 __ mov(ecx, var->name()); |
1207 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 1212 Handle<Code> ic(isolate()->builtins()->builtin( |
| 1213 Builtins::LoadIC_Initialize)); |
1208 EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); | 1214 EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); |
1209 context()->Plug(eax); | 1215 context()->Plug(eax); |
1210 | 1216 |
1211 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { | 1217 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { |
1212 Label done, slow; | 1218 Label done, slow; |
1213 | 1219 |
1214 // Generate code for loading from variables potentially shadowed | 1220 // Generate code for loading from variables potentially shadowed |
1215 // by eval-introduced variables. | 1221 // by eval-introduced variables. |
1216 EmitDynamicLoadFromSlotFastCase(slot, NOT_INSIDE_TYPEOF, &slow, &done); | 1222 EmitDynamicLoadFromSlotFastCase(slot, NOT_INSIDE_TYPEOF, &slow, &done); |
1217 | 1223 |
1218 __ bind(&slow); | 1224 __ bind(&slow); |
1219 Comment cmnt(masm_, "Lookup slot"); | 1225 Comment cmnt(masm_, "Lookup slot"); |
1220 __ push(esi); // Context. | 1226 __ push(esi); // Context. |
1221 __ push(Immediate(var->name())); | 1227 __ push(Immediate(var->name())); |
1222 __ CallRuntime(Runtime::kLoadContextSlot, 2); | 1228 __ CallRuntime(Runtime::kLoadContextSlot, 2); |
1223 __ bind(&done); | 1229 __ bind(&done); |
1224 | 1230 |
1225 context()->Plug(eax); | 1231 context()->Plug(eax); |
1226 | 1232 |
1227 } else if (slot != NULL) { | 1233 } else if (slot != NULL) { |
1228 Comment cmnt(masm_, (slot->type() == Slot::CONTEXT) | 1234 Comment cmnt(masm_, (slot->type() == Slot::CONTEXT) |
1229 ? "Context slot" | 1235 ? "Context slot" |
1230 : "Stack slot"); | 1236 : "Stack slot"); |
1231 if (var->mode() == Variable::CONST) { | 1237 if (var->mode() == Variable::CONST) { |
1232 // Constants may be the hole value if they have not been initialized. | 1238 // Constants may be the hole value if they have not been initialized. |
1233 // Unhole them. | 1239 // Unhole them. |
1234 NearLabel done; | 1240 NearLabel done; |
1235 MemOperand slot_operand = EmitSlotSearch(slot, eax); | 1241 MemOperand slot_operand = EmitSlotSearch(slot, eax); |
1236 __ mov(eax, slot_operand); | 1242 __ mov(eax, slot_operand); |
1237 __ cmp(eax, Factory::the_hole_value()); | 1243 __ cmp(eax, isolate()->factory()->the_hole_value()); |
1238 __ j(not_equal, &done); | 1244 __ j(not_equal, &done); |
1239 __ mov(eax, Factory::undefined_value()); | 1245 __ mov(eax, isolate()->factory()->undefined_value()); |
1240 __ bind(&done); | 1246 __ bind(&done); |
1241 context()->Plug(eax); | 1247 context()->Plug(eax); |
1242 } else { | 1248 } else { |
1243 context()->Plug(slot); | 1249 context()->Plug(slot); |
1244 } | 1250 } |
1245 | 1251 |
1246 } else { | 1252 } else { |
1247 Comment cmnt(masm_, "Rewritten parameter"); | 1253 Comment cmnt(masm_, "Rewritten parameter"); |
1248 ASSERT_NOT_NULL(property); | 1254 ASSERT_NOT_NULL(property); |
1249 // Rewritten parameter accesses are of the form "slot[literal]". | 1255 // Rewritten parameter accesses are of the form "slot[literal]". |
(...skipping 10 matching lines...) Expand all Loading... |
1260 | 1266 |
1261 // Assert that the key is a smi. | 1267 // Assert that the key is a smi. |
1262 Literal* key_literal = property->key()->AsLiteral(); | 1268 Literal* key_literal = property->key()->AsLiteral(); |
1263 ASSERT_NOT_NULL(key_literal); | 1269 ASSERT_NOT_NULL(key_literal); |
1264 ASSERT(key_literal->handle()->IsSmi()); | 1270 ASSERT(key_literal->handle()->IsSmi()); |
1265 | 1271 |
1266 // Load the key. | 1272 // Load the key. |
1267 __ mov(eax, Immediate(key_literal->handle())); | 1273 __ mov(eax, Immediate(key_literal->handle())); |
1268 | 1274 |
1269 // Do a keyed property load. | 1275 // Do a keyed property load. |
1270 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 1276 Handle<Code> ic(isolate()->builtins()->builtin( |
| 1277 Builtins::KeyedLoadIC_Initialize)); |
1271 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 1278 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
1272 | 1279 |
1273 // Drop key and object left on the stack by IC. | 1280 // Drop key and object left on the stack by IC. |
1274 context()->Plug(eax); | 1281 context()->Plug(eax); |
1275 } | 1282 } |
1276 } | 1283 } |
1277 | 1284 |
1278 | 1285 |
1279 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { | 1286 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { |
1280 Comment cmnt(masm_, "[ RegExpLiteral"); | 1287 Comment cmnt(masm_, "[ RegExpLiteral"); |
1281 NearLabel materialized; | 1288 NearLabel materialized; |
1282 // Registers will be used as follows: | 1289 // Registers will be used as follows: |
1283 // edi = JS function. | 1290 // edi = JS function. |
1284 // ecx = literals array. | 1291 // ecx = literals array. |
1285 // ebx = regexp literal. | 1292 // ebx = regexp literal. |
1286 // eax = regexp literal clone. | 1293 // eax = regexp literal clone. |
1287 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); | 1294 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
1288 __ mov(ecx, FieldOperand(edi, JSFunction::kLiteralsOffset)); | 1295 __ mov(ecx, FieldOperand(edi, JSFunction::kLiteralsOffset)); |
1289 int literal_offset = | 1296 int literal_offset = |
1290 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; | 1297 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; |
1291 __ mov(ebx, FieldOperand(ecx, literal_offset)); | 1298 __ mov(ebx, FieldOperand(ecx, literal_offset)); |
1292 __ cmp(ebx, Factory::undefined_value()); | 1299 __ cmp(ebx, isolate()->factory()->undefined_value()); |
1293 __ j(not_equal, &materialized); | 1300 __ j(not_equal, &materialized); |
1294 | 1301 |
1295 // Create regexp literal using runtime function | 1302 // Create regexp literal using runtime function |
1296 // Result will be in eax. | 1303 // Result will be in eax. |
1297 __ push(ecx); | 1304 __ push(ecx); |
1298 __ push(Immediate(Smi::FromInt(expr->literal_index()))); | 1305 __ push(Immediate(Smi::FromInt(expr->literal_index()))); |
1299 __ push(Immediate(expr->pattern())); | 1306 __ push(Immediate(expr->pattern())); |
1300 __ push(Immediate(expr->flags())); | 1307 __ push(Immediate(expr->flags())); |
1301 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); | 1308 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); |
1302 __ mov(ebx, eax); | 1309 __ mov(ebx, eax); |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1365 switch (property->kind()) { | 1372 switch (property->kind()) { |
1366 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | 1373 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
1367 ASSERT(!CompileTimeValue::IsCompileTimeValue(value)); | 1374 ASSERT(!CompileTimeValue::IsCompileTimeValue(value)); |
1368 // Fall through. | 1375 // Fall through. |
1369 case ObjectLiteral::Property::COMPUTED: | 1376 case ObjectLiteral::Property::COMPUTED: |
1370 if (key->handle()->IsSymbol()) { | 1377 if (key->handle()->IsSymbol()) { |
1371 if (property->emit_store()) { | 1378 if (property->emit_store()) { |
1372 VisitForAccumulatorValue(value); | 1379 VisitForAccumulatorValue(value); |
1373 __ mov(ecx, Immediate(key->handle())); | 1380 __ mov(ecx, Immediate(key->handle())); |
1374 __ mov(edx, Operand(esp, 0)); | 1381 __ mov(edx, Operand(esp, 0)); |
1375 Handle<Code> ic(Builtins::builtin( | 1382 Handle<Code> ic(isolate()->builtins()->builtin( |
1376 is_strict_mode() ? Builtins::StoreIC_Initialize_Strict | 1383 is_strict_mode() ? Builtins::StoreIC_Initialize_Strict |
1377 : Builtins::StoreIC_Initialize)); | 1384 : Builtins::StoreIC_Initialize)); |
1378 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 1385 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
1379 PrepareForBailoutForId(key->id(), NO_REGISTERS); | 1386 PrepareForBailoutForId(key->id(), NO_REGISTERS); |
1380 } else { | 1387 } else { |
1381 VisitForEffect(value); | 1388 VisitForEffect(value); |
1382 } | 1389 } |
1383 break; | 1390 break; |
1384 } | 1391 } |
1385 // Fall through. | 1392 // Fall through. |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1419 void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { | 1426 void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { |
1420 Comment cmnt(masm_, "[ ArrayLiteral"); | 1427 Comment cmnt(masm_, "[ ArrayLiteral"); |
1421 | 1428 |
1422 ZoneList<Expression*>* subexprs = expr->values(); | 1429 ZoneList<Expression*>* subexprs = expr->values(); |
1423 int length = subexprs->length(); | 1430 int length = subexprs->length(); |
1424 | 1431 |
1425 __ mov(ebx, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); | 1432 __ mov(ebx, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
1426 __ push(FieldOperand(ebx, JSFunction::kLiteralsOffset)); | 1433 __ push(FieldOperand(ebx, JSFunction::kLiteralsOffset)); |
1427 __ push(Immediate(Smi::FromInt(expr->literal_index()))); | 1434 __ push(Immediate(Smi::FromInt(expr->literal_index()))); |
1428 __ push(Immediate(expr->constant_elements())); | 1435 __ push(Immediate(expr->constant_elements())); |
1429 if (expr->constant_elements()->map() == Heap::fixed_cow_array_map()) { | 1436 if (expr->constant_elements()->map() == |
| 1437 isolate()->heap()->fixed_cow_array_map()) { |
1430 ASSERT(expr->depth() == 1); | 1438 ASSERT(expr->depth() == 1); |
1431 FastCloneShallowArrayStub stub( | 1439 FastCloneShallowArrayStub stub( |
1432 FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS, length); | 1440 FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS, length); |
1433 __ CallStub(&stub); | 1441 __ CallStub(&stub); |
1434 __ IncrementCounter(&Counters::cow_arrays_created_stub, 1); | 1442 __ IncrementCounter(isolate()->counters()->cow_arrays_created_stub(), 1); |
1435 } else if (expr->depth() > 1) { | 1443 } else if (expr->depth() > 1) { |
1436 __ CallRuntime(Runtime::kCreateArrayLiteral, 3); | 1444 __ CallRuntime(Runtime::kCreateArrayLiteral, 3); |
1437 } else if (length > FastCloneShallowArrayStub::kMaximumClonedLength) { | 1445 } else if (length > FastCloneShallowArrayStub::kMaximumClonedLength) { |
1438 __ CallRuntime(Runtime::kCreateArrayLiteralShallow, 3); | 1446 __ CallRuntime(Runtime::kCreateArrayLiteralShallow, 3); |
1439 } else { | 1447 } else { |
1440 FastCloneShallowArrayStub stub( | 1448 FastCloneShallowArrayStub stub( |
1441 FastCloneShallowArrayStub::CLONE_ELEMENTS, length); | 1449 FastCloneShallowArrayStub::CLONE_ELEMENTS, length); |
1442 __ CallStub(&stub); | 1450 __ CallStub(&stub); |
1443 } | 1451 } |
1444 | 1452 |
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1609 EmitKeyedPropertyAssignment(expr); | 1617 EmitKeyedPropertyAssignment(expr); |
1610 break; | 1618 break; |
1611 } | 1619 } |
1612 } | 1620 } |
1613 | 1621 |
1614 | 1622 |
1615 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { | 1623 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { |
1616 SetSourcePosition(prop->position()); | 1624 SetSourcePosition(prop->position()); |
1617 Literal* key = prop->key()->AsLiteral(); | 1625 Literal* key = prop->key()->AsLiteral(); |
1618 __ mov(ecx, Immediate(key->handle())); | 1626 __ mov(ecx, Immediate(key->handle())); |
1619 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 1627 Handle<Code> ic(isolate()->builtins()->builtin( |
| 1628 Builtins::LoadIC_Initialize)); |
1620 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 1629 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
1621 } | 1630 } |
1622 | 1631 |
1623 | 1632 |
1624 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { | 1633 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { |
1625 SetSourcePosition(prop->position()); | 1634 SetSourcePosition(prop->position()); |
1626 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 1635 Handle<Code> ic(isolate()->builtins()->builtin( |
| 1636 Builtins::KeyedLoadIC_Initialize)); |
1627 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 1637 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
1628 } | 1638 } |
1629 | 1639 |
1630 | 1640 |
1631 void FullCodeGenerator::EmitInlineSmiBinaryOp(Expression* expr, | 1641 void FullCodeGenerator::EmitInlineSmiBinaryOp(Expression* expr, |
1632 Token::Value op, | 1642 Token::Value op, |
1633 OverwriteMode mode, | 1643 OverwriteMode mode, |
1634 Expression* left, | 1644 Expression* left, |
1635 Expression* right) { | 1645 Expression* right) { |
1636 // Do combined smi check of the operands. Left operand is on the | 1646 // Do combined smi check of the operands. Left operand is on the |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1757 EffectContext context(this); | 1767 EffectContext context(this); |
1758 EmitVariableAssignment(var, Token::ASSIGN); | 1768 EmitVariableAssignment(var, Token::ASSIGN); |
1759 break; | 1769 break; |
1760 } | 1770 } |
1761 case NAMED_PROPERTY: { | 1771 case NAMED_PROPERTY: { |
1762 __ push(eax); // Preserve value. | 1772 __ push(eax); // Preserve value. |
1763 VisitForAccumulatorValue(prop->obj()); | 1773 VisitForAccumulatorValue(prop->obj()); |
1764 __ mov(edx, eax); | 1774 __ mov(edx, eax); |
1765 __ pop(eax); // Restore value. | 1775 __ pop(eax); // Restore value. |
1766 __ mov(ecx, prop->key()->AsLiteral()->handle()); | 1776 __ mov(ecx, prop->key()->AsLiteral()->handle()); |
1767 Handle<Code> ic(Builtins::builtin( | 1777 Handle<Code> ic(isolate()->builtins()->builtin( |
1768 is_strict_mode() ? Builtins::StoreIC_Initialize_Strict | 1778 is_strict_mode() ? Builtins::StoreIC_Initialize_Strict |
1769 : Builtins::StoreIC_Initialize)); | 1779 : Builtins::StoreIC_Initialize)); |
1770 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 1780 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
1771 break; | 1781 break; |
1772 } | 1782 } |
1773 case KEYED_PROPERTY: { | 1783 case KEYED_PROPERTY: { |
1774 __ push(eax); // Preserve value. | 1784 __ push(eax); // Preserve value. |
1775 if (prop->is_synthetic()) { | 1785 if (prop->is_synthetic()) { |
1776 ASSERT(prop->obj()->AsVariableProxy() != NULL); | 1786 ASSERT(prop->obj()->AsVariableProxy() != NULL); |
1777 ASSERT(prop->key()->AsLiteral() != NULL); | 1787 ASSERT(prop->key()->AsLiteral() != NULL); |
1778 { AccumulatorValueContext for_object(this); | 1788 { AccumulatorValueContext for_object(this); |
1779 EmitVariableLoad(prop->obj()->AsVariableProxy()->var()); | 1789 EmitVariableLoad(prop->obj()->AsVariableProxy()->var()); |
1780 } | 1790 } |
1781 __ mov(edx, eax); | 1791 __ mov(edx, eax); |
1782 __ Set(ecx, Immediate(prop->key()->AsLiteral()->handle())); | 1792 __ Set(ecx, Immediate(prop->key()->AsLiteral()->handle())); |
1783 } else { | 1793 } else { |
1784 VisitForStackValue(prop->obj()); | 1794 VisitForStackValue(prop->obj()); |
1785 VisitForAccumulatorValue(prop->key()); | 1795 VisitForAccumulatorValue(prop->key()); |
1786 __ mov(ecx, eax); | 1796 __ mov(ecx, eax); |
1787 __ pop(edx); | 1797 __ pop(edx); |
1788 } | 1798 } |
1789 __ pop(eax); // Restore value. | 1799 __ pop(eax); // Restore value. |
1790 Handle<Code> ic(Builtins::builtin( | 1800 Handle<Code> ic(isolate()->builtins()->builtin( |
1791 is_strict_mode() ? Builtins::KeyedStoreIC_Initialize_Strict | 1801 is_strict_mode() ? Builtins::KeyedStoreIC_Initialize_Strict |
1792 : Builtins::KeyedStoreIC_Initialize)); | 1802 : Builtins::KeyedStoreIC_Initialize)); |
1793 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 1803 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
1794 break; | 1804 break; |
1795 } | 1805 } |
1796 } | 1806 } |
1797 PrepareForBailoutForId(bailout_ast_id, TOS_REG); | 1807 PrepareForBailoutForId(bailout_ast_id, TOS_REG); |
1798 context()->Plug(eax); | 1808 context()->Plug(eax); |
1799 } | 1809 } |
1800 | 1810 |
1801 | 1811 |
1802 void FullCodeGenerator::EmitVariableAssignment(Variable* var, | 1812 void FullCodeGenerator::EmitVariableAssignment(Variable* var, |
1803 Token::Value op) { | 1813 Token::Value op) { |
1804 // Left-hand sides that rewrite to explicit property accesses do not reach | 1814 // Left-hand sides that rewrite to explicit property accesses do not reach |
1805 // here. | 1815 // here. |
1806 ASSERT(var != NULL); | 1816 ASSERT(var != NULL); |
1807 ASSERT(var->is_global() || var->AsSlot() != NULL); | 1817 ASSERT(var->is_global() || var->AsSlot() != NULL); |
1808 | 1818 |
1809 if (var->is_global()) { | 1819 if (var->is_global()) { |
1810 ASSERT(!var->is_this()); | 1820 ASSERT(!var->is_this()); |
1811 // Assignment to a global variable. Use inline caching for the | 1821 // Assignment to a global variable. Use inline caching for the |
1812 // assignment. Right-hand-side value is passed in eax, variable name in | 1822 // assignment. Right-hand-side value is passed in eax, variable name in |
1813 // ecx, and the global object on the stack. | 1823 // ecx, and the global object on the stack. |
1814 __ mov(ecx, var->name()); | 1824 __ mov(ecx, var->name()); |
1815 __ mov(edx, GlobalObjectOperand()); | 1825 __ mov(edx, GlobalObjectOperand()); |
1816 Handle<Code> ic(Builtins::builtin( | 1826 Handle<Code> ic(isolate()->builtins()->builtin( |
1817 is_strict_mode() ? Builtins::StoreIC_Initialize_Strict | 1827 is_strict_mode() ? Builtins::StoreIC_Initialize_Strict |
1818 : Builtins::StoreIC_Initialize)); | 1828 : Builtins::StoreIC_Initialize)); |
1819 EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); | 1829 EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); |
1820 | 1830 |
1821 } else if (op == Token::INIT_CONST) { | 1831 } else if (op == Token::INIT_CONST) { |
1822 // Like var declarations, const declarations are hoisted to function | 1832 // Like var declarations, const declarations are hoisted to function |
1823 // scope. However, unlike var initializers, const initializers are able | 1833 // scope. However, unlike var initializers, const initializers are able |
1824 // to drill a hole to that function context, even from inside a 'with' | 1834 // to drill a hole to that function context, even from inside a 'with' |
1825 // context. We thus bypass the normal static scope lookup. | 1835 // context. We thus bypass the normal static scope lookup. |
1826 Slot* slot = var->AsSlot(); | 1836 Slot* slot = var->AsSlot(); |
1827 Label skip; | 1837 Label skip; |
1828 switch (slot->type()) { | 1838 switch (slot->type()) { |
1829 case Slot::PARAMETER: | 1839 case Slot::PARAMETER: |
1830 // No const parameters. | 1840 // No const parameters. |
1831 UNREACHABLE(); | 1841 UNREACHABLE(); |
1832 break; | 1842 break; |
1833 case Slot::LOCAL: | 1843 case Slot::LOCAL: |
1834 __ mov(edx, Operand(ebp, SlotOffset(slot))); | 1844 __ mov(edx, Operand(ebp, SlotOffset(slot))); |
1835 __ cmp(edx, Factory::the_hole_value()); | 1845 __ cmp(edx, isolate()->factory()->the_hole_value()); |
1836 __ j(not_equal, &skip); | 1846 __ j(not_equal, &skip); |
1837 __ mov(Operand(ebp, SlotOffset(slot)), eax); | 1847 __ mov(Operand(ebp, SlotOffset(slot)), eax); |
1838 break; | 1848 break; |
1839 case Slot::CONTEXT: { | 1849 case Slot::CONTEXT: { |
1840 __ mov(ecx, ContextOperand(esi, Context::FCONTEXT_INDEX)); | 1850 __ mov(ecx, ContextOperand(esi, Context::FCONTEXT_INDEX)); |
1841 __ mov(edx, ContextOperand(ecx, slot->index())); | 1851 __ mov(edx, ContextOperand(ecx, slot->index())); |
1842 __ cmp(edx, Factory::the_hole_value()); | 1852 __ cmp(edx, isolate()->factory()->the_hole_value()); |
1843 __ j(not_equal, &skip); | 1853 __ j(not_equal, &skip); |
1844 __ mov(ContextOperand(ecx, slot->index()), eax); | 1854 __ mov(ContextOperand(ecx, slot->index()), eax); |
1845 int offset = Context::SlotOffset(slot->index()); | 1855 int offset = Context::SlotOffset(slot->index()); |
1846 __ mov(edx, eax); // Preserve the stored value in eax. | 1856 __ mov(edx, eax); // Preserve the stored value in eax. |
1847 __ RecordWrite(ecx, offset, edx, ebx); | 1857 __ RecordWrite(ecx, offset, edx, ebx); |
1848 break; | 1858 break; |
1849 } | 1859 } |
1850 case Slot::LOOKUP: | 1860 case Slot::LOOKUP: |
1851 __ push(eax); | 1861 __ push(eax); |
1852 __ push(esi); | 1862 __ push(esi); |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1909 } | 1919 } |
1910 | 1920 |
1911 // Record source code position before IC call. | 1921 // Record source code position before IC call. |
1912 SetSourcePosition(expr->position()); | 1922 SetSourcePosition(expr->position()); |
1913 __ mov(ecx, prop->key()->AsLiteral()->handle()); | 1923 __ mov(ecx, prop->key()->AsLiteral()->handle()); |
1914 if (expr->ends_initialization_block()) { | 1924 if (expr->ends_initialization_block()) { |
1915 __ mov(edx, Operand(esp, 0)); | 1925 __ mov(edx, Operand(esp, 0)); |
1916 } else { | 1926 } else { |
1917 __ pop(edx); | 1927 __ pop(edx); |
1918 } | 1928 } |
1919 Handle<Code> ic(Builtins::builtin( | 1929 Handle<Code> ic(isolate()->builtins()->builtin( |
1920 is_strict_mode() ? Builtins::StoreIC_Initialize_Strict | 1930 is_strict_mode() ? Builtins::StoreIC_Initialize_Strict |
1921 : Builtins::StoreIC_Initialize)); | 1931 : Builtins::StoreIC_Initialize)); |
1922 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 1932 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
1923 | 1933 |
1924 // If the assignment ends an initialization block, revert to fast case. | 1934 // If the assignment ends an initialization block, revert to fast case. |
1925 if (expr->ends_initialization_block()) { | 1935 if (expr->ends_initialization_block()) { |
1926 __ push(eax); // Result of assignment, saved even if not needed. | 1936 __ push(eax); // Result of assignment, saved even if not needed. |
1927 __ push(Operand(esp, kPointerSize)); // Receiver is under value. | 1937 __ push(Operand(esp, kPointerSize)); // Receiver is under value. |
1928 __ CallRuntime(Runtime::kToFastProperties, 1); | 1938 __ CallRuntime(Runtime::kToFastProperties, 1); |
1929 __ pop(eax); | 1939 __ pop(eax); |
(...skipping 19 matching lines...) Expand all Loading... |
1949 } | 1959 } |
1950 | 1960 |
1951 __ pop(ecx); | 1961 __ pop(ecx); |
1952 if (expr->ends_initialization_block()) { | 1962 if (expr->ends_initialization_block()) { |
1953 __ mov(edx, Operand(esp, 0)); // Leave receiver on the stack for later. | 1963 __ mov(edx, Operand(esp, 0)); // Leave receiver on the stack for later. |
1954 } else { | 1964 } else { |
1955 __ pop(edx); | 1965 __ pop(edx); |
1956 } | 1966 } |
1957 // Record source code position before IC call. | 1967 // Record source code position before IC call. |
1958 SetSourcePosition(expr->position()); | 1968 SetSourcePosition(expr->position()); |
1959 Handle<Code> ic(Builtins::builtin( | 1969 Handle<Code> ic(isolate()->builtins()->builtin( |
1960 is_strict_mode() ? Builtins::KeyedStoreIC_Initialize_Strict | 1970 is_strict_mode() ? Builtins::KeyedStoreIC_Initialize_Strict |
1961 : Builtins::KeyedStoreIC_Initialize)); | 1971 : Builtins::KeyedStoreIC_Initialize)); |
1962 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 1972 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
1963 | 1973 |
1964 // If the assignment ends an initialization block, revert to fast case. | 1974 // If the assignment ends an initialization block, revert to fast case. |
1965 if (expr->ends_initialization_block()) { | 1975 if (expr->ends_initialization_block()) { |
1966 __ pop(edx); | 1976 __ pop(edx); |
1967 __ push(eax); // Result of assignment, saved even if not needed. | 1977 __ push(eax); // Result of assignment, saved even if not needed. |
1968 __ push(edx); | 1978 __ push(edx); |
1969 __ CallRuntime(Runtime::kToFastProperties, 1); | 1979 __ CallRuntime(Runtime::kToFastProperties, 1); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2001 int arg_count = args->length(); | 2011 int arg_count = args->length(); |
2002 { PreservePositionScope scope(masm()->positions_recorder()); | 2012 { PreservePositionScope scope(masm()->positions_recorder()); |
2003 for (int i = 0; i < arg_count; i++) { | 2013 for (int i = 0; i < arg_count; i++) { |
2004 VisitForStackValue(args->at(i)); | 2014 VisitForStackValue(args->at(i)); |
2005 } | 2015 } |
2006 __ Set(ecx, Immediate(name)); | 2016 __ Set(ecx, Immediate(name)); |
2007 } | 2017 } |
2008 // Record source position of the IC call. | 2018 // Record source position of the IC call. |
2009 SetSourcePosition(expr->position()); | 2019 SetSourcePosition(expr->position()); |
2010 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; | 2020 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; |
2011 Handle<Code> ic = StubCache::ComputeCallInitialize(arg_count, in_loop); | 2021 Handle<Code> ic = isolate()->stub_cache()->ComputeCallInitialize( |
| 2022 arg_count, in_loop); |
2012 EmitCallIC(ic, mode); | 2023 EmitCallIC(ic, mode); |
2013 RecordJSReturnSite(expr); | 2024 RecordJSReturnSite(expr); |
2014 // Restore context register. | 2025 // Restore context register. |
2015 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 2026 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
2016 context()->Plug(eax); | 2027 context()->Plug(eax); |
2017 } | 2028 } |
2018 | 2029 |
2019 | 2030 |
2020 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, | 2031 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, |
2021 Expression* key, | 2032 Expression* key, |
(...skipping 11 matching lines...) Expand all Loading... |
2033 ZoneList<Expression*>* args = expr->arguments(); | 2044 ZoneList<Expression*>* args = expr->arguments(); |
2034 int arg_count = args->length(); | 2045 int arg_count = args->length(); |
2035 { PreservePositionScope scope(masm()->positions_recorder()); | 2046 { PreservePositionScope scope(masm()->positions_recorder()); |
2036 for (int i = 0; i < arg_count; i++) { | 2047 for (int i = 0; i < arg_count; i++) { |
2037 VisitForStackValue(args->at(i)); | 2048 VisitForStackValue(args->at(i)); |
2038 } | 2049 } |
2039 } | 2050 } |
2040 // Record source position of the IC call. | 2051 // Record source position of the IC call. |
2041 SetSourcePosition(expr->position()); | 2052 SetSourcePosition(expr->position()); |
2042 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; | 2053 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; |
2043 Handle<Code> ic = StubCache::ComputeKeyedCallInitialize(arg_count, in_loop); | 2054 Handle<Code> ic = isolate()->stub_cache()->ComputeKeyedCallInitialize( |
| 2055 arg_count, in_loop); |
2044 __ mov(ecx, Operand(esp, (arg_count + 1) * kPointerSize)); // Key. | 2056 __ mov(ecx, Operand(esp, (arg_count + 1) * kPointerSize)); // Key. |
2045 EmitCallIC(ic, mode); | 2057 EmitCallIC(ic, mode); |
2046 RecordJSReturnSite(expr); | 2058 RecordJSReturnSite(expr); |
2047 // Restore context register. | 2059 // Restore context register. |
2048 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 2060 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
2049 context()->DropAndPlug(1, eax); // Drop the key still on the stack. | 2061 context()->DropAndPlug(1, eax); // Drop the key still on the stack. |
2050 } | 2062 } |
2051 | 2063 |
2052 | 2064 |
2053 void FullCodeGenerator::EmitCallWithStub(Call* expr) { | 2065 void FullCodeGenerator::EmitCallWithStub(Call* expr) { |
(...skipping 16 matching lines...) Expand all Loading... |
2070 context()->DropAndPlug(1, eax); | 2082 context()->DropAndPlug(1, eax); |
2071 } | 2083 } |
2072 | 2084 |
2073 | 2085 |
2074 void FullCodeGenerator::EmitResolvePossiblyDirectEval(ResolveEvalFlag flag, | 2086 void FullCodeGenerator::EmitResolvePossiblyDirectEval(ResolveEvalFlag flag, |
2075 int arg_count) { | 2087 int arg_count) { |
2076 // Push copy of the first argument or undefined if it doesn't exist. | 2088 // Push copy of the first argument or undefined if it doesn't exist. |
2077 if (arg_count > 0) { | 2089 if (arg_count > 0) { |
2078 __ push(Operand(esp, arg_count * kPointerSize)); | 2090 __ push(Operand(esp, arg_count * kPointerSize)); |
2079 } else { | 2091 } else { |
2080 __ push(Immediate(Factory::undefined_value())); | 2092 __ push(Immediate(FACTORY->undefined_value())); |
2081 } | 2093 } |
2082 | 2094 |
2083 // Push the receiver of the enclosing function. | 2095 // Push the receiver of the enclosing function. |
2084 __ push(Operand(ebp, (2 + scope()->num_parameters()) * kPointerSize)); | 2096 __ push(Operand(ebp, (2 + scope()->num_parameters()) * kPointerSize)); |
2085 | 2097 |
2086 // Push the strict mode flag. | 2098 // Push the strict mode flag. |
2087 __ push(Immediate(Smi::FromInt(strict_mode_flag()))); | 2099 __ push(Immediate(Smi::FromInt(strict_mode_flag()))); |
2088 | 2100 |
2089 __ CallRuntime(flag == SKIP_CONTEXT_LOOKUP | 2101 __ CallRuntime(flag == SKIP_CONTEXT_LOOKUP |
2090 ? Runtime::kResolvePossiblyDirectEvalNoLookup | 2102 ? Runtime::kResolvePossiblyDirectEvalNoLookup |
(...skipping 15 matching lines...) Expand all Loading... |
2106 if (var != NULL && var->is_possibly_eval()) { | 2118 if (var != NULL && var->is_possibly_eval()) { |
2107 // In a call to eval, we first call %ResolvePossiblyDirectEval to | 2119 // In a call to eval, we first call %ResolvePossiblyDirectEval to |
2108 // resolve the function we need to call and the receiver of the | 2120 // resolve the function we need to call and the receiver of the |
2109 // call. Then we call the resolved function using the given | 2121 // call. Then we call the resolved function using the given |
2110 // arguments. | 2122 // arguments. |
2111 ZoneList<Expression*>* args = expr->arguments(); | 2123 ZoneList<Expression*>* args = expr->arguments(); |
2112 int arg_count = args->length(); | 2124 int arg_count = args->length(); |
2113 { PreservePositionScope pos_scope(masm()->positions_recorder()); | 2125 { PreservePositionScope pos_scope(masm()->positions_recorder()); |
2114 VisitForStackValue(fun); | 2126 VisitForStackValue(fun); |
2115 // Reserved receiver slot. | 2127 // Reserved receiver slot. |
2116 __ push(Immediate(Factory::undefined_value())); | 2128 __ push(Immediate(isolate()->factory()->undefined_value())); |
2117 | 2129 |
2118 // Push the arguments. | 2130 // Push the arguments. |
2119 for (int i = 0; i < arg_count; i++) { | 2131 for (int i = 0; i < arg_count; i++) { |
2120 VisitForStackValue(args->at(i)); | 2132 VisitForStackValue(args->at(i)); |
2121 } | 2133 } |
2122 | 2134 |
2123 // If we know that eval can only be shadowed by eval-introduced | 2135 // If we know that eval can only be shadowed by eval-introduced |
2124 // variables we attempt to load the global eval function directly | 2136 // variables we attempt to load the global eval function directly |
2125 // in generated code. If we succeed, there is no need to perform a | 2137 // in generated code. If we succeed, there is no need to perform a |
2126 // context lookup in the runtime system. | 2138 // context lookup in the runtime system. |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2225 MemOperand operand = EmitSlotSearch(slot, edx); | 2237 MemOperand operand = EmitSlotSearch(slot, edx); |
2226 __ mov(edx, operand); | 2238 __ mov(edx, operand); |
2227 | 2239 |
2228 ASSERT(prop->key()->AsLiteral() != NULL); | 2240 ASSERT(prop->key()->AsLiteral() != NULL); |
2229 ASSERT(prop->key()->AsLiteral()->handle()->IsSmi()); | 2241 ASSERT(prop->key()->AsLiteral()->handle()->IsSmi()); |
2230 __ mov(eax, prop->key()->AsLiteral()->handle()); | 2242 __ mov(eax, prop->key()->AsLiteral()->handle()); |
2231 | 2243 |
2232 // Record source code position for IC call. | 2244 // Record source code position for IC call. |
2233 SetSourcePosition(prop->position()); | 2245 SetSourcePosition(prop->position()); |
2234 | 2246 |
2235 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 2247 Handle<Code> ic(isolate()->builtins()->builtin( |
| 2248 Builtins::KeyedLoadIC_Initialize)); |
2236 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 2249 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
2237 // Push result (function). | 2250 // Push result (function). |
2238 __ push(eax); | 2251 __ push(eax); |
2239 // Push Global receiver. | 2252 // Push Global receiver. |
2240 __ mov(ecx, GlobalObjectOperand()); | 2253 __ mov(ecx, GlobalObjectOperand()); |
2241 __ push(FieldOperand(ecx, GlobalObject::kGlobalReceiverOffset)); | 2254 __ push(FieldOperand(ecx, GlobalObject::kGlobalReceiverOffset)); |
2242 EmitCallWithStub(expr); | 2255 EmitCallWithStub(expr); |
2243 } else { | 2256 } else { |
2244 { PreservePositionScope scope(masm()->positions_recorder()); | 2257 { PreservePositionScope scope(masm()->positions_recorder()); |
2245 VisitForStackValue(prop->obj()); | 2258 VisitForStackValue(prop->obj()); |
2246 } | 2259 } |
2247 EmitKeyedCallWithIC(expr, prop->key(), RelocInfo::CODE_TARGET); | 2260 EmitKeyedCallWithIC(expr, prop->key(), RelocInfo::CODE_TARGET); |
2248 } | 2261 } |
2249 } | 2262 } |
2250 } else { | 2263 } else { |
2251 // Call to some other expression. If the expression is an anonymous | 2264 // Call to some other expression. If the expression is an anonymous |
2252 // function literal not called in a loop, mark it as one that should | 2265 // function literal not called in a loop, mark it as one that should |
2253 // also use the full code generator. | 2266 // also use the full code generator. |
2254 FunctionLiteral* lit = fun->AsFunctionLiteral(); | 2267 FunctionLiteral* lit = fun->AsFunctionLiteral(); |
2255 if (lit != NULL && | 2268 if (lit != NULL && |
2256 lit->name()->Equals(Heap::empty_string()) && | 2269 lit->name()->Equals(isolate()->heap()->empty_string()) && |
2257 loop_depth() == 0) { | 2270 loop_depth() == 0) { |
2258 lit->set_try_full_codegen(true); | 2271 lit->set_try_full_codegen(true); |
2259 } | 2272 } |
2260 { PreservePositionScope scope(masm()->positions_recorder()); | 2273 { PreservePositionScope scope(masm()->positions_recorder()); |
2261 VisitForStackValue(fun); | 2274 VisitForStackValue(fun); |
2262 } | 2275 } |
2263 // Load global receiver object. | 2276 // Load global receiver object. |
2264 __ mov(ebx, GlobalObjectOperand()); | 2277 __ mov(ebx, GlobalObjectOperand()); |
2265 __ push(FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset)); | 2278 __ push(FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset)); |
2266 // Emit function call. | 2279 // Emit function call. |
(...skipping 26 matching lines...) Expand all Loading... |
2293 } | 2306 } |
2294 | 2307 |
2295 // Call the construct call builtin that handles allocation and | 2308 // Call the construct call builtin that handles allocation and |
2296 // constructor invocation. | 2309 // constructor invocation. |
2297 SetSourcePosition(expr->position()); | 2310 SetSourcePosition(expr->position()); |
2298 | 2311 |
2299 // Load function and argument count into edi and eax. | 2312 // Load function and argument count into edi and eax. |
2300 __ Set(eax, Immediate(arg_count)); | 2313 __ Set(eax, Immediate(arg_count)); |
2301 __ mov(edi, Operand(esp, arg_count * kPointerSize)); | 2314 __ mov(edi, Operand(esp, arg_count * kPointerSize)); |
2302 | 2315 |
2303 Handle<Code> construct_builtin(Builtins::builtin(Builtins::JSConstructCall)); | 2316 Handle<Code> construct_builtin(isolate()->builtins()->builtin( |
| 2317 Builtins::JSConstructCall)); |
2304 __ call(construct_builtin, RelocInfo::CONSTRUCT_CALL); | 2318 __ call(construct_builtin, RelocInfo::CONSTRUCT_CALL); |
2305 context()->Plug(eax); | 2319 context()->Plug(eax); |
2306 } | 2320 } |
2307 | 2321 |
2308 | 2322 |
2309 void FullCodeGenerator::EmitIsSmi(ZoneList<Expression*>* args) { | 2323 void FullCodeGenerator::EmitIsSmi(ZoneList<Expression*>* args) { |
2310 ASSERT(args->length() == 1); | 2324 ASSERT(args->length() == 1); |
2311 | 2325 |
2312 VisitForAccumulatorValue(args->at(0)); | 2326 VisitForAccumulatorValue(args->at(0)); |
2313 | 2327 |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2353 | 2367 |
2354 Label materialize_true, materialize_false; | 2368 Label materialize_true, materialize_false; |
2355 Label* if_true = NULL; | 2369 Label* if_true = NULL; |
2356 Label* if_false = NULL; | 2370 Label* if_false = NULL; |
2357 Label* fall_through = NULL; | 2371 Label* fall_through = NULL; |
2358 context()->PrepareTest(&materialize_true, &materialize_false, | 2372 context()->PrepareTest(&materialize_true, &materialize_false, |
2359 &if_true, &if_false, &fall_through); | 2373 &if_true, &if_false, &fall_through); |
2360 | 2374 |
2361 __ test(eax, Immediate(kSmiTagMask)); | 2375 __ test(eax, Immediate(kSmiTagMask)); |
2362 __ j(zero, if_false); | 2376 __ j(zero, if_false); |
2363 __ cmp(eax, Factory::null_value()); | 2377 __ cmp(eax, isolate()->factory()->null_value()); |
2364 __ j(equal, if_true); | 2378 __ j(equal, if_true); |
2365 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); | 2379 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); |
2366 // Undetectable objects behave like undefined when tested with typeof. | 2380 // Undetectable objects behave like undefined when tested with typeof. |
2367 __ movzx_b(ecx, FieldOperand(ebx, Map::kBitFieldOffset)); | 2381 __ movzx_b(ecx, FieldOperand(ebx, Map::kBitFieldOffset)); |
2368 __ test(ecx, Immediate(1 << Map::kIsUndetectable)); | 2382 __ test(ecx, Immediate(1 << Map::kIsUndetectable)); |
2369 __ j(not_zero, if_false); | 2383 __ j(not_zero, if_false); |
2370 __ movzx_b(ecx, FieldOperand(ebx, Map::kInstanceTypeOffset)); | 2384 __ movzx_b(ecx, FieldOperand(ebx, Map::kInstanceTypeOffset)); |
2371 __ cmp(ecx, FIRST_JS_OBJECT_TYPE); | 2385 __ cmp(ecx, FIRST_JS_OBJECT_TYPE); |
2372 __ j(below, if_false); | 2386 __ j(below, if_false); |
2373 __ cmp(ecx, LAST_JS_OBJECT_TYPE); | 2387 __ cmp(ecx, LAST_JS_OBJECT_TYPE); |
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2632 __ j(not_equal, &non_function_constructor); | 2646 __ j(not_equal, &non_function_constructor); |
2633 | 2647 |
2634 // eax now contains the constructor function. Grab the | 2648 // eax now contains the constructor function. Grab the |
2635 // instance class name from there. | 2649 // instance class name from there. |
2636 __ mov(eax, FieldOperand(eax, JSFunction::kSharedFunctionInfoOffset)); | 2650 __ mov(eax, FieldOperand(eax, JSFunction::kSharedFunctionInfoOffset)); |
2637 __ mov(eax, FieldOperand(eax, SharedFunctionInfo::kInstanceClassNameOffset)); | 2651 __ mov(eax, FieldOperand(eax, SharedFunctionInfo::kInstanceClassNameOffset)); |
2638 __ jmp(&done); | 2652 __ jmp(&done); |
2639 | 2653 |
2640 // Functions have class 'Function'. | 2654 // Functions have class 'Function'. |
2641 __ bind(&function); | 2655 __ bind(&function); |
2642 __ mov(eax, Factory::function_class_symbol()); | 2656 __ mov(eax, isolate()->factory()->function_class_symbol()); |
2643 __ jmp(&done); | 2657 __ jmp(&done); |
2644 | 2658 |
2645 // Objects with a non-function constructor have class 'Object'. | 2659 // Objects with a non-function constructor have class 'Object'. |
2646 __ bind(&non_function_constructor); | 2660 __ bind(&non_function_constructor); |
2647 __ mov(eax, Factory::Object_symbol()); | 2661 __ mov(eax, isolate()->factory()->Object_symbol()); |
2648 __ jmp(&done); | 2662 __ jmp(&done); |
2649 | 2663 |
2650 // Non-JS objects have class null. | 2664 // Non-JS objects have class null. |
2651 __ bind(&null); | 2665 __ bind(&null); |
2652 __ mov(eax, Factory::null_value()); | 2666 __ mov(eax, isolate()->factory()->null_value()); |
2653 | 2667 |
2654 // All done. | 2668 // All done. |
2655 __ bind(&done); | 2669 __ bind(&done); |
2656 | 2670 |
2657 context()->Plug(eax); | 2671 context()->Plug(eax); |
2658 } | 2672 } |
2659 | 2673 |
2660 | 2674 |
2661 void FullCodeGenerator::EmitLog(ZoneList<Expression*>* args) { | 2675 void FullCodeGenerator::EmitLog(ZoneList<Expression*>* args) { |
2662 // Conditionally generate a log call. | 2676 // Conditionally generate a log call. |
2663 // Args: | 2677 // Args: |
2664 // 0 (literal string): The type of logging (corresponds to the flags). | 2678 // 0 (literal string): The type of logging (corresponds to the flags). |
2665 // This is used to determine whether or not to generate the log call. | 2679 // This is used to determine whether or not to generate the log call. |
2666 // 1 (string): Format string. Access the string at argument index 2 | 2680 // 1 (string): Format string. Access the string at argument index 2 |
2667 // with '%2s' (see Logger::LogRuntime for all the formats). | 2681 // with '%2s' (see Logger::LogRuntime for all the formats). |
2668 // 2 (array): Arguments to the format string. | 2682 // 2 (array): Arguments to the format string. |
2669 ASSERT_EQ(args->length(), 3); | 2683 ASSERT_EQ(args->length(), 3); |
2670 #ifdef ENABLE_LOGGING_AND_PROFILING | 2684 #ifdef ENABLE_LOGGING_AND_PROFILING |
2671 if (CodeGenerator::ShouldGenerateLog(args->at(0))) { | 2685 if (CodeGenerator::ShouldGenerateLog(args->at(0))) { |
2672 VisitForStackValue(args->at(1)); | 2686 VisitForStackValue(args->at(1)); |
2673 VisitForStackValue(args->at(2)); | 2687 VisitForStackValue(args->at(2)); |
2674 __ CallRuntime(Runtime::kLog, 2); | 2688 __ CallRuntime(Runtime::kLog, 2); |
2675 } | 2689 } |
2676 #endif | 2690 #endif |
2677 // Finally, we're expected to leave a value on the top of the stack. | 2691 // Finally, we're expected to leave a value on the top of the stack. |
2678 __ mov(eax, Factory::undefined_value()); | 2692 __ mov(eax, isolate()->factory()->undefined_value()); |
2679 context()->Plug(eax); | 2693 context()->Plug(eax); |
2680 } | 2694 } |
2681 | 2695 |
2682 | 2696 |
2683 void FullCodeGenerator::EmitRandomHeapNumber(ZoneList<Expression*>* args) { | 2697 void FullCodeGenerator::EmitRandomHeapNumber(ZoneList<Expression*>* args) { |
2684 ASSERT(args->length() == 0); | 2698 ASSERT(args->length() == 0); |
2685 | 2699 |
2686 Label slow_allocate_heapnumber; | 2700 Label slow_allocate_heapnumber; |
2687 Label heapnumber_allocated; | 2701 Label heapnumber_allocated; |
2688 | 2702 |
2689 __ AllocateHeapNumber(edi, ebx, ecx, &slow_allocate_heapnumber); | 2703 __ AllocateHeapNumber(edi, ebx, ecx, &slow_allocate_heapnumber); |
2690 __ jmp(&heapnumber_allocated); | 2704 __ jmp(&heapnumber_allocated); |
2691 | 2705 |
2692 __ bind(&slow_allocate_heapnumber); | 2706 __ bind(&slow_allocate_heapnumber); |
2693 // Allocate a heap number. | 2707 // Allocate a heap number. |
2694 __ CallRuntime(Runtime::kNumberAlloc, 0); | 2708 __ CallRuntime(Runtime::kNumberAlloc, 0); |
2695 __ mov(edi, eax); | 2709 __ mov(edi, eax); |
2696 | 2710 |
2697 __ bind(&heapnumber_allocated); | 2711 __ bind(&heapnumber_allocated); |
2698 | 2712 |
2699 __ PrepareCallCFunction(0, ebx); | 2713 __ PrepareCallCFunction(0, ebx); |
2700 __ CallCFunction(ExternalReference::random_uint32_function(), 0); | 2714 __ CallCFunction(ExternalReference::random_uint32_function(), 0); |
2701 | 2715 |
2702 // Convert 32 random bits in eax to 0.(32 random bits) in a double | 2716 // Convert 32 random bits in eax to 0.(32 random bits) in a double |
2703 // by computing: | 2717 // by computing: |
2704 // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)). | 2718 // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)). |
2705 // This is implemented on both SSE2 and FPU. | 2719 // This is implemented on both SSE2 and FPU. |
2706 if (CpuFeatures::IsSupported(SSE2)) { | 2720 if (isolate()->cpu_features()->IsSupported(SSE2)) { |
2707 CpuFeatures::Scope fscope(SSE2); | 2721 CpuFeatures::Scope fscope(SSE2); |
2708 __ mov(ebx, Immediate(0x49800000)); // 1.0 x 2^20 as single. | 2722 __ mov(ebx, Immediate(0x49800000)); // 1.0 x 2^20 as single. |
2709 __ movd(xmm1, Operand(ebx)); | 2723 __ movd(xmm1, Operand(ebx)); |
2710 __ movd(xmm0, Operand(eax)); | 2724 __ movd(xmm0, Operand(eax)); |
2711 __ cvtss2sd(xmm1, xmm1); | 2725 __ cvtss2sd(xmm1, xmm1); |
2712 __ pxor(xmm0, xmm1); | 2726 __ pxor(xmm0, xmm1); |
2713 __ subsd(xmm0, xmm1); | 2727 __ subsd(xmm0, xmm1); |
2714 __ movdbl(FieldOperand(edi, HeapNumber::kValueOffset), xmm0); | 2728 __ movdbl(FieldOperand(edi, HeapNumber::kValueOffset), xmm0); |
2715 } else { | 2729 } else { |
2716 // 0x4130000000000000 is 1.0 x 2^20 as a double. | 2730 // 0x4130000000000000 is 1.0 x 2^20 as a double. |
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2865 &need_conversion, | 2879 &need_conversion, |
2866 &need_conversion, | 2880 &need_conversion, |
2867 &index_out_of_range, | 2881 &index_out_of_range, |
2868 STRING_INDEX_IS_NUMBER); | 2882 STRING_INDEX_IS_NUMBER); |
2869 generator.GenerateFast(masm_); | 2883 generator.GenerateFast(masm_); |
2870 __ jmp(&done); | 2884 __ jmp(&done); |
2871 | 2885 |
2872 __ bind(&index_out_of_range); | 2886 __ bind(&index_out_of_range); |
2873 // When the index is out of range, the spec requires us to return | 2887 // When the index is out of range, the spec requires us to return |
2874 // NaN. | 2888 // NaN. |
2875 __ Set(result, Immediate(Factory::nan_value())); | 2889 __ Set(result, Immediate(isolate()->factory()->nan_value())); |
2876 __ jmp(&done); | 2890 __ jmp(&done); |
2877 | 2891 |
2878 __ bind(&need_conversion); | 2892 __ bind(&need_conversion); |
2879 // Move the undefined value into the result register, which will | 2893 // Move the undefined value into the result register, which will |
2880 // trigger conversion. | 2894 // trigger conversion. |
2881 __ Set(result, Immediate(Factory::undefined_value())); | 2895 __ Set(result, Immediate(isolate()->factory()->undefined_value())); |
2882 __ jmp(&done); | 2896 __ jmp(&done); |
2883 | 2897 |
2884 NopRuntimeCallHelper call_helper; | 2898 NopRuntimeCallHelper call_helper; |
2885 generator.GenerateSlow(masm_, call_helper); | 2899 generator.GenerateSlow(masm_, call_helper); |
2886 | 2900 |
2887 __ bind(&done); | 2901 __ bind(&done); |
2888 context()->Plug(result); | 2902 context()->Plug(result); |
2889 } | 2903 } |
2890 | 2904 |
2891 | 2905 |
(...skipping 22 matching lines...) Expand all Loading... |
2914 &need_conversion, | 2928 &need_conversion, |
2915 &need_conversion, | 2929 &need_conversion, |
2916 &index_out_of_range, | 2930 &index_out_of_range, |
2917 STRING_INDEX_IS_NUMBER); | 2931 STRING_INDEX_IS_NUMBER); |
2918 generator.GenerateFast(masm_); | 2932 generator.GenerateFast(masm_); |
2919 __ jmp(&done); | 2933 __ jmp(&done); |
2920 | 2934 |
2921 __ bind(&index_out_of_range); | 2935 __ bind(&index_out_of_range); |
2922 // When the index is out of range, the spec requires us to return | 2936 // When the index is out of range, the spec requires us to return |
2923 // the empty string. | 2937 // the empty string. |
2924 __ Set(result, Immediate(Factory::empty_string())); | 2938 __ Set(result, Immediate(isolate()->factory()->empty_string())); |
2925 __ jmp(&done); | 2939 __ jmp(&done); |
2926 | 2940 |
2927 __ bind(&need_conversion); | 2941 __ bind(&need_conversion); |
2928 // Move smi zero into the result register, which will trigger | 2942 // Move smi zero into the result register, which will trigger |
2929 // conversion. | 2943 // conversion. |
2930 __ Set(result, Immediate(Smi::FromInt(0))); | 2944 __ Set(result, Immediate(Smi::FromInt(0))); |
2931 __ jmp(&done); | 2945 __ jmp(&done); |
2932 | 2946 |
2933 NopRuntimeCallHelper call_helper; | 2947 NopRuntimeCallHelper call_helper; |
2934 generator.GenerateSlow(masm_, call_helper); | 2948 generator.GenerateSlow(masm_, call_helper); |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3053 // has no indexed interceptor. | 3067 // has no indexed interceptor. |
3054 __ CmpObjectType(object, JS_ARRAY_TYPE, temp); | 3068 __ CmpObjectType(object, JS_ARRAY_TYPE, temp); |
3055 __ j(not_equal, &slow_case); | 3069 __ j(not_equal, &slow_case); |
3056 __ test_b(FieldOperand(temp, Map::kBitFieldOffset), | 3070 __ test_b(FieldOperand(temp, Map::kBitFieldOffset), |
3057 KeyedLoadIC::kSlowCaseBitFieldMask); | 3071 KeyedLoadIC::kSlowCaseBitFieldMask); |
3058 __ j(not_zero, &slow_case); | 3072 __ j(not_zero, &slow_case); |
3059 | 3073 |
3060 // Check the object's elements are in fast case and writable. | 3074 // Check the object's elements are in fast case and writable. |
3061 __ mov(elements, FieldOperand(object, JSObject::kElementsOffset)); | 3075 __ mov(elements, FieldOperand(object, JSObject::kElementsOffset)); |
3062 __ cmp(FieldOperand(elements, HeapObject::kMapOffset), | 3076 __ cmp(FieldOperand(elements, HeapObject::kMapOffset), |
3063 Immediate(Factory::fixed_array_map())); | 3077 Immediate(isolate()->factory()->fixed_array_map())); |
3064 __ j(not_equal, &slow_case); | 3078 __ j(not_equal, &slow_case); |
3065 | 3079 |
3066 // Check that both indices are smis. | 3080 // Check that both indices are smis. |
3067 __ mov(index_1, Operand(esp, 1 * kPointerSize)); | 3081 __ mov(index_1, Operand(esp, 1 * kPointerSize)); |
3068 __ mov(index_2, Operand(esp, 0)); | 3082 __ mov(index_2, Operand(esp, 0)); |
3069 __ mov(temp, index_1); | 3083 __ mov(temp, index_1); |
3070 __ or_(temp, Operand(index_2)); | 3084 __ or_(temp, Operand(index_2)); |
3071 __ test(temp, Immediate(kSmiTagMask)); | 3085 __ test(temp, Immediate(kSmiTagMask)); |
3072 __ j(not_zero, &slow_case); | 3086 __ j(not_zero, &slow_case); |
3073 | 3087 |
(...skipping 17 matching lines...) Expand all Loading... |
3091 Label new_space; | 3105 Label new_space; |
3092 __ InNewSpace(elements, temp, equal, &new_space); | 3106 __ InNewSpace(elements, temp, equal, &new_space); |
3093 | 3107 |
3094 __ mov(object, elements); | 3108 __ mov(object, elements); |
3095 __ RecordWriteHelper(object, index_1, temp); | 3109 __ RecordWriteHelper(object, index_1, temp); |
3096 __ RecordWriteHelper(elements, index_2, temp); | 3110 __ RecordWriteHelper(elements, index_2, temp); |
3097 | 3111 |
3098 __ bind(&new_space); | 3112 __ bind(&new_space); |
3099 // We are done. Drop elements from the stack, and return undefined. | 3113 // We are done. Drop elements from the stack, and return undefined. |
3100 __ add(Operand(esp), Immediate(3 * kPointerSize)); | 3114 __ add(Operand(esp), Immediate(3 * kPointerSize)); |
3101 __ mov(eax, Factory::undefined_value()); | 3115 __ mov(eax, isolate()->factory()->undefined_value()); |
3102 __ jmp(&done); | 3116 __ jmp(&done); |
3103 | 3117 |
3104 __ bind(&slow_case); | 3118 __ bind(&slow_case); |
3105 __ CallRuntime(Runtime::kSwapElements, 3); | 3119 __ CallRuntime(Runtime::kSwapElements, 3); |
3106 | 3120 |
3107 __ bind(&done); | 3121 __ bind(&done); |
3108 context()->Plug(eax); | 3122 context()->Plug(eax); |
3109 } | 3123 } |
3110 | 3124 |
3111 | 3125 |
3112 void FullCodeGenerator::EmitGetFromCache(ZoneList<Expression*>* args) { | 3126 void FullCodeGenerator::EmitGetFromCache(ZoneList<Expression*>* args) { |
3113 ASSERT_EQ(2, args->length()); | 3127 ASSERT_EQ(2, args->length()); |
3114 | 3128 |
3115 ASSERT_NE(NULL, args->at(0)->AsLiteral()); | 3129 ASSERT_NE(NULL, args->at(0)->AsLiteral()); |
3116 int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->handle()))->value(); | 3130 int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->handle()))->value(); |
3117 | 3131 |
3118 Handle<FixedArray> jsfunction_result_caches( | 3132 Handle<FixedArray> jsfunction_result_caches( |
3119 Top::global_context()->jsfunction_result_caches()); | 3133 isolate()->global_context()->jsfunction_result_caches()); |
3120 if (jsfunction_result_caches->length() <= cache_id) { | 3134 if (jsfunction_result_caches->length() <= cache_id) { |
3121 __ Abort("Attempt to use undefined cache."); | 3135 __ Abort("Attempt to use undefined cache."); |
3122 __ mov(eax, Factory::undefined_value()); | 3136 __ mov(eax, isolate()->factory()->undefined_value()); |
3123 context()->Plug(eax); | 3137 context()->Plug(eax); |
3124 return; | 3138 return; |
3125 } | 3139 } |
3126 | 3140 |
3127 VisitForAccumulatorValue(args->at(1)); | 3141 VisitForAccumulatorValue(args->at(1)); |
3128 | 3142 |
3129 Register key = eax; | 3143 Register key = eax; |
3130 Register cache = ebx; | 3144 Register cache = ebx; |
3131 Register tmp = ecx; | 3145 Register tmp = ecx; |
3132 __ mov(cache, ContextOperand(esi, Context::GLOBAL_INDEX)); | 3146 __ mov(cache, ContextOperand(esi, Context::GLOBAL_INDEX)); |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3169 __ pop(left); | 3183 __ pop(left); |
3170 | 3184 |
3171 Label done, fail, ok; | 3185 Label done, fail, ok; |
3172 __ cmp(left, Operand(right)); | 3186 __ cmp(left, Operand(right)); |
3173 __ j(equal, &ok); | 3187 __ j(equal, &ok); |
3174 // Fail if either is a non-HeapObject. | 3188 // Fail if either is a non-HeapObject. |
3175 __ mov(tmp, left); | 3189 __ mov(tmp, left); |
3176 __ and_(Operand(tmp), right); | 3190 __ and_(Operand(tmp), right); |
3177 __ test(Operand(tmp), Immediate(kSmiTagMask)); | 3191 __ test(Operand(tmp), Immediate(kSmiTagMask)); |
3178 __ j(zero, &fail); | 3192 __ j(zero, &fail); |
3179 __ CmpObjectType(left, JS_REGEXP_TYPE, tmp); | 3193 __ mov(tmp, FieldOperand(left, HeapObject::kMapOffset)); |
| 3194 __ CmpInstanceType(tmp, JS_REGEXP_TYPE); |
3180 __ j(not_equal, &fail); | 3195 __ j(not_equal, &fail); |
3181 __ cmp(tmp, FieldOperand(right, HeapObject::kMapOffset)); | 3196 __ cmp(tmp, FieldOperand(right, HeapObject::kMapOffset)); |
3182 __ j(not_equal, &fail); | 3197 __ j(not_equal, &fail); |
3183 __ mov(tmp, FieldOperand(left, JSRegExp::kDataOffset)); | 3198 __ mov(tmp, FieldOperand(left, JSRegExp::kDataOffset)); |
3184 __ cmp(tmp, FieldOperand(right, JSRegExp::kDataOffset)); | 3199 __ cmp(tmp, FieldOperand(right, JSRegExp::kDataOffset)); |
3185 __ j(equal, &ok); | 3200 __ j(equal, &ok); |
3186 __ bind(&fail); | 3201 __ bind(&fail); |
3187 __ mov(eax, Immediate(Factory::false_value())); | 3202 __ mov(eax, Immediate(isolate()->factory()->false_value())); |
3188 __ jmp(&done); | 3203 __ jmp(&done); |
3189 __ bind(&ok); | 3204 __ bind(&ok); |
3190 __ mov(eax, Immediate(Factory::true_value())); | 3205 __ mov(eax, Immediate(isolate()->factory()->true_value())); |
3191 __ bind(&done); | 3206 __ bind(&done); |
3192 | 3207 |
3193 context()->Plug(eax); | 3208 context()->Plug(eax); |
3194 } | 3209 } |
3195 | 3210 |
3196 | 3211 |
3197 void FullCodeGenerator::EmitHasCachedArrayIndex(ZoneList<Expression*>* args) { | 3212 void FullCodeGenerator::EmitHasCachedArrayIndex(ZoneList<Expression*>* args) { |
3198 ASSERT(args->length() == 1); | 3213 ASSERT(args->length() == 1); |
3199 | 3214 |
3200 VisitForAccumulatorValue(args->at(0)); | 3215 VisitForAccumulatorValue(args->at(0)); |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3273 | 3288 |
3274 // Check that the array has fast elements. | 3289 // Check that the array has fast elements. |
3275 __ test_b(FieldOperand(scratch, Map::kBitField2Offset), | 3290 __ test_b(FieldOperand(scratch, Map::kBitField2Offset), |
3276 1 << Map::kHasFastElements); | 3291 1 << Map::kHasFastElements); |
3277 __ j(zero, &bailout); | 3292 __ j(zero, &bailout); |
3278 | 3293 |
3279 // If the array has length zero, return the empty string. | 3294 // If the array has length zero, return the empty string. |
3280 __ mov(array_length, FieldOperand(array, JSArray::kLengthOffset)); | 3295 __ mov(array_length, FieldOperand(array, JSArray::kLengthOffset)); |
3281 __ SmiUntag(array_length); | 3296 __ SmiUntag(array_length); |
3282 __ j(not_zero, &non_trivial_array); | 3297 __ j(not_zero, &non_trivial_array); |
3283 __ mov(result_operand, Factory::empty_string()); | 3298 __ mov(result_operand, FACTORY->empty_string()); |
3284 __ jmp(&done); | 3299 __ jmp(&done); |
3285 | 3300 |
3286 // Save the array length. | 3301 // Save the array length. |
3287 __ bind(&non_trivial_array); | 3302 __ bind(&non_trivial_array); |
3288 __ mov(array_length_operand, array_length); | 3303 __ mov(array_length_operand, array_length); |
3289 | 3304 |
3290 // Save the FixedArray containing array's elements. | 3305 // Save the FixedArray containing array's elements. |
3291 // End of array's live range. | 3306 // End of array's live range. |
3292 elements = array; | 3307 elements = array; |
3293 __ mov(elements, FieldOperand(array, JSArray::kElementsOffset)); | 3308 __ mov(elements, FieldOperand(array, JSArray::kElementsOffset)); |
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3484 FieldOperand(string, SeqAsciiString::kHeaderSize)); | 3499 FieldOperand(string, SeqAsciiString::kHeaderSize)); |
3485 __ CopyBytes(string, result_pos, string_length, scratch); | 3500 __ CopyBytes(string, result_pos, string_length, scratch); |
3486 __ add(Operand(index), Immediate(1)); | 3501 __ add(Operand(index), Immediate(1)); |
3487 | 3502 |
3488 __ cmp(index, array_length_operand); | 3503 __ cmp(index, array_length_operand); |
3489 __ j(less, &loop_3); // End while (index < length). | 3504 __ j(less, &loop_3); // End while (index < length). |
3490 __ jmp(&done); | 3505 __ jmp(&done); |
3491 | 3506 |
3492 | 3507 |
3493 __ bind(&bailout); | 3508 __ bind(&bailout); |
3494 __ mov(result_operand, Factory::undefined_value()); | 3509 __ mov(result_operand, FACTORY->undefined_value()); |
3495 __ bind(&done); | 3510 __ bind(&done); |
3496 __ mov(eax, result_operand); | 3511 __ mov(eax, result_operand); |
3497 // Drop temp values from the stack, and restore context register. | 3512 // Drop temp values from the stack, and restore context register. |
3498 __ add(Operand(esp), Immediate(3 * kPointerSize)); | 3513 __ add(Operand(esp), Immediate(3 * kPointerSize)); |
3499 | 3514 |
3500 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 3515 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
3501 context()->Plug(eax); | 3516 context()->Plug(eax); |
3502 } | 3517 } |
3503 | 3518 |
3504 | 3519 |
(...skipping 17 matching lines...) Expand all Loading... |
3522 // Push the arguments ("left-to-right"). | 3537 // Push the arguments ("left-to-right"). |
3523 int arg_count = args->length(); | 3538 int arg_count = args->length(); |
3524 for (int i = 0; i < arg_count; i++) { | 3539 for (int i = 0; i < arg_count; i++) { |
3525 VisitForStackValue(args->at(i)); | 3540 VisitForStackValue(args->at(i)); |
3526 } | 3541 } |
3527 | 3542 |
3528 if (expr->is_jsruntime()) { | 3543 if (expr->is_jsruntime()) { |
3529 // Call the JS runtime function via a call IC. | 3544 // Call the JS runtime function via a call IC. |
3530 __ Set(ecx, Immediate(expr->name())); | 3545 __ Set(ecx, Immediate(expr->name())); |
3531 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; | 3546 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; |
3532 Handle<Code> ic = StubCache::ComputeCallInitialize(arg_count, in_loop); | 3547 Handle<Code> ic = isolate()->stub_cache()->ComputeCallInitialize( |
| 3548 arg_count, in_loop); |
3533 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 3549 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
3534 // Restore context register. | 3550 // Restore context register. |
3535 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 3551 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
3536 } else { | 3552 } else { |
3537 // Call the C runtime function. | 3553 // Call the C runtime function. |
3538 __ CallRuntime(expr->function(), arg_count); | 3554 __ CallRuntime(expr->function(), arg_count); |
3539 } | 3555 } |
3540 context()->Plug(eax); | 3556 context()->Plug(eax); |
3541 } | 3557 } |
3542 | 3558 |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3588 // The subexpression may have side effects. | 3604 // The subexpression may have side effects. |
3589 VisitForEffect(expr->expression()); | 3605 VisitForEffect(expr->expression()); |
3590 context()->Plug(true); | 3606 context()->Plug(true); |
3591 } | 3607 } |
3592 break; | 3608 break; |
3593 } | 3609 } |
3594 | 3610 |
3595 case Token::VOID: { | 3611 case Token::VOID: { |
3596 Comment cmnt(masm_, "[ UnaryOperation (VOID)"); | 3612 Comment cmnt(masm_, "[ UnaryOperation (VOID)"); |
3597 VisitForEffect(expr->expression()); | 3613 VisitForEffect(expr->expression()); |
3598 context()->Plug(Factory::undefined_value()); | 3614 context()->Plug(isolate()->factory()->undefined_value()); |
3599 break; | 3615 break; |
3600 } | 3616 } |
3601 | 3617 |
3602 case Token::NOT: { | 3618 case Token::NOT: { |
3603 Comment cmnt(masm_, "[ UnaryOperation (NOT)"); | 3619 Comment cmnt(masm_, "[ UnaryOperation (NOT)"); |
3604 if (context()->IsEffect()) { | 3620 if (context()->IsEffect()) { |
3605 // Unary NOT has no side effects so it's only necessary to visit the | 3621 // Unary NOT has no side effects so it's only necessary to visit the |
3606 // subexpression. Match the optimizing compiler by not branching. | 3622 // subexpression. Match the optimizing compiler by not branching. |
3607 VisitForEffect(expr->expression()); | 3623 VisitForEffect(expr->expression()); |
3608 } else { | 3624 } else { |
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3836 // Perform the assignment as if via '='. | 3852 // Perform the assignment as if via '='. |
3837 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), | 3853 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
3838 Token::ASSIGN); | 3854 Token::ASSIGN); |
3839 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 3855 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
3840 context()->Plug(eax); | 3856 context()->Plug(eax); |
3841 } | 3857 } |
3842 break; | 3858 break; |
3843 case NAMED_PROPERTY: { | 3859 case NAMED_PROPERTY: { |
3844 __ mov(ecx, prop->key()->AsLiteral()->handle()); | 3860 __ mov(ecx, prop->key()->AsLiteral()->handle()); |
3845 __ pop(edx); | 3861 __ pop(edx); |
3846 Handle<Code> ic(Builtins::builtin( | 3862 Handle<Code> ic(isolate()->builtins()->builtin( |
3847 is_strict_mode() ? Builtins::StoreIC_Initialize_Strict | 3863 is_strict_mode() ? Builtins::StoreIC_Initialize_Strict |
3848 : Builtins::StoreIC_Initialize)); | 3864 : Builtins::StoreIC_Initialize)); |
3849 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 3865 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
3850 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 3866 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
3851 if (expr->is_postfix()) { | 3867 if (expr->is_postfix()) { |
3852 if (!context()->IsEffect()) { | 3868 if (!context()->IsEffect()) { |
3853 context()->PlugTOS(); | 3869 context()->PlugTOS(); |
3854 } | 3870 } |
3855 } else { | 3871 } else { |
3856 context()->Plug(eax); | 3872 context()->Plug(eax); |
3857 } | 3873 } |
3858 break; | 3874 break; |
3859 } | 3875 } |
3860 case KEYED_PROPERTY: { | 3876 case KEYED_PROPERTY: { |
3861 __ pop(ecx); | 3877 __ pop(ecx); |
3862 __ pop(edx); | 3878 __ pop(edx); |
3863 Handle<Code> ic(Builtins::builtin( | 3879 Handle<Code> ic(isolate()->builtins()->builtin( |
3864 is_strict_mode() ? Builtins::KeyedStoreIC_Initialize_Strict | 3880 is_strict_mode() ? Builtins::KeyedStoreIC_Initialize_Strict |
3865 : Builtins::KeyedStoreIC_Initialize)); | 3881 : Builtins::KeyedStoreIC_Initialize)); |
3866 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 3882 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
3867 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 3883 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
3868 if (expr->is_postfix()) { | 3884 if (expr->is_postfix()) { |
3869 // Result is on the stack | 3885 // Result is on the stack |
3870 if (!context()->IsEffect()) { | 3886 if (!context()->IsEffect()) { |
3871 context()->PlugTOS(); | 3887 context()->PlugTOS(); |
3872 } | 3888 } |
3873 } else { | 3889 } else { |
3874 context()->Plug(eax); | 3890 context()->Plug(eax); |
3875 } | 3891 } |
3876 break; | 3892 break; |
3877 } | 3893 } |
3878 } | 3894 } |
3879 } | 3895 } |
3880 | 3896 |
3881 | 3897 |
3882 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { | 3898 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { |
3883 VariableProxy* proxy = expr->AsVariableProxy(); | 3899 VariableProxy* proxy = expr->AsVariableProxy(); |
3884 ASSERT(!context()->IsEffect()); | 3900 ASSERT(!context()->IsEffect()); |
3885 ASSERT(!context()->IsTest()); | 3901 ASSERT(!context()->IsTest()); |
3886 | 3902 |
3887 if (proxy != NULL && !proxy->var()->is_this() && proxy->var()->is_global()) { | 3903 if (proxy != NULL && !proxy->var()->is_this() && proxy->var()->is_global()) { |
3888 Comment cmnt(masm_, "Global variable"); | 3904 Comment cmnt(masm_, "Global variable"); |
3889 __ mov(eax, GlobalObjectOperand()); | 3905 __ mov(eax, GlobalObjectOperand()); |
3890 __ mov(ecx, Immediate(proxy->name())); | 3906 __ mov(ecx, Immediate(proxy->name())); |
3891 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 3907 Handle<Code> ic(isolate()->builtins()->builtin( |
| 3908 Builtins::LoadIC_Initialize)); |
3892 // Use a regular load, not a contextual load, to avoid a reference | 3909 // Use a regular load, not a contextual load, to avoid a reference |
3893 // error. | 3910 // error. |
3894 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 3911 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
3895 PrepareForBailout(expr, TOS_REG); | 3912 PrepareForBailout(expr, TOS_REG); |
3896 context()->Plug(eax); | 3913 context()->Plug(eax); |
3897 } else if (proxy != NULL && | 3914 } else if (proxy != NULL && |
3898 proxy->var()->AsSlot() != NULL && | 3915 proxy->var()->AsSlot() != NULL && |
3899 proxy->var()->AsSlot()->type() == Slot::LOOKUP) { | 3916 proxy->var()->AsSlot()->type() == Slot::LOOKUP) { |
3900 Label done, slow; | 3917 Label done, slow; |
3901 | 3918 |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3934 if (!right_literal_value->IsString()) return false; | 3951 if (!right_literal_value->IsString()) return false; |
3935 UnaryOperation* left_unary = left->AsUnaryOperation(); | 3952 UnaryOperation* left_unary = left->AsUnaryOperation(); |
3936 if (left_unary == NULL || left_unary->op() != Token::TYPEOF) return false; | 3953 if (left_unary == NULL || left_unary->op() != Token::TYPEOF) return false; |
3937 Handle<String> check = Handle<String>::cast(right_literal_value); | 3954 Handle<String> check = Handle<String>::cast(right_literal_value); |
3938 | 3955 |
3939 { AccumulatorValueContext context(this); | 3956 { AccumulatorValueContext context(this); |
3940 VisitForTypeofValue(left_unary->expression()); | 3957 VisitForTypeofValue(left_unary->expression()); |
3941 } | 3958 } |
3942 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); | 3959 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); |
3943 | 3960 |
3944 if (check->Equals(Heap::number_symbol())) { | 3961 if (check->Equals(isolate()->heap()->number_symbol())) { |
3945 __ JumpIfSmi(eax, if_true); | 3962 __ JumpIfSmi(eax, if_true); |
3946 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), | 3963 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), |
3947 Factory::heap_number_map()); | 3964 isolate()->factory()->heap_number_map()); |
3948 Split(equal, if_true, if_false, fall_through); | 3965 Split(equal, if_true, if_false, fall_through); |
3949 } else if (check->Equals(Heap::string_symbol())) { | 3966 } else if (check->Equals(isolate()->heap()->string_symbol())) { |
3950 __ JumpIfSmi(eax, if_false); | 3967 __ JumpIfSmi(eax, if_false); |
3951 __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, edx); | 3968 __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, edx); |
3952 __ j(above_equal, if_false); | 3969 __ j(above_equal, if_false); |
3953 // Check for undetectable objects => false. | 3970 // Check for undetectable objects => false. |
3954 __ test_b(FieldOperand(edx, Map::kBitFieldOffset), | 3971 __ test_b(FieldOperand(edx, Map::kBitFieldOffset), |
3955 1 << Map::kIsUndetectable); | 3972 1 << Map::kIsUndetectable); |
3956 Split(zero, if_true, if_false, fall_through); | 3973 Split(zero, if_true, if_false, fall_through); |
3957 } else if (check->Equals(Heap::boolean_symbol())) { | 3974 } else if (check->Equals(isolate()->heap()->boolean_symbol())) { |
3958 __ cmp(eax, Factory::true_value()); | 3975 __ cmp(eax, isolate()->factory()->true_value()); |
3959 __ j(equal, if_true); | 3976 __ j(equal, if_true); |
3960 __ cmp(eax, Factory::false_value()); | 3977 __ cmp(eax, isolate()->factory()->false_value()); |
3961 Split(equal, if_true, if_false, fall_through); | 3978 Split(equal, if_true, if_false, fall_through); |
3962 } else if (check->Equals(Heap::undefined_symbol())) { | 3979 } else if (check->Equals(isolate()->heap()->undefined_symbol())) { |
3963 __ cmp(eax, Factory::undefined_value()); | 3980 __ cmp(eax, isolate()->factory()->undefined_value()); |
3964 __ j(equal, if_true); | 3981 __ j(equal, if_true); |
3965 __ JumpIfSmi(eax, if_false); | 3982 __ JumpIfSmi(eax, if_false); |
3966 // Check for undetectable objects => true. | 3983 // Check for undetectable objects => true. |
3967 __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset)); | 3984 __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset)); |
3968 __ movzx_b(ecx, FieldOperand(edx, Map::kBitFieldOffset)); | 3985 __ movzx_b(ecx, FieldOperand(edx, Map::kBitFieldOffset)); |
3969 __ test(ecx, Immediate(1 << Map::kIsUndetectable)); | 3986 __ test(ecx, Immediate(1 << Map::kIsUndetectable)); |
3970 Split(not_zero, if_true, if_false, fall_through); | 3987 Split(not_zero, if_true, if_false, fall_through); |
3971 } else if (check->Equals(Heap::function_symbol())) { | 3988 } else if (check->Equals(isolate()->heap()->function_symbol())) { |
3972 __ JumpIfSmi(eax, if_false); | 3989 __ JumpIfSmi(eax, if_false); |
3973 __ CmpObjectType(eax, FIRST_FUNCTION_CLASS_TYPE, edx); | 3990 __ CmpObjectType(eax, FIRST_FUNCTION_CLASS_TYPE, edx); |
3974 Split(above_equal, if_true, if_false, fall_through); | 3991 Split(above_equal, if_true, if_false, fall_through); |
3975 } else if (check->Equals(Heap::object_symbol())) { | 3992 } else if (check->Equals(isolate()->heap()->object_symbol())) { |
3976 __ JumpIfSmi(eax, if_false); | 3993 __ JumpIfSmi(eax, if_false); |
3977 __ cmp(eax, Factory::null_value()); | 3994 __ cmp(eax, isolate()->factory()->null_value()); |
3978 __ j(equal, if_true); | 3995 __ j(equal, if_true); |
3979 __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, edx); | 3996 __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, edx); |
3980 __ j(below, if_false); | 3997 __ j(below, if_false); |
3981 __ CmpInstanceType(edx, FIRST_FUNCTION_CLASS_TYPE); | 3998 __ CmpInstanceType(edx, FIRST_FUNCTION_CLASS_TYPE); |
3982 __ j(above_equal, if_false); | 3999 __ j(above_equal, if_false); |
3983 // Check for undetectable objects => false. | 4000 // Check for undetectable objects => false. |
3984 __ test_b(FieldOperand(edx, Map::kBitFieldOffset), | 4001 __ test_b(FieldOperand(edx, Map::kBitFieldOffset), |
3985 1 << Map::kIsUndetectable); | 4002 1 << Map::kIsUndetectable); |
3986 Split(zero, if_true, if_false, fall_through); | 4003 Split(zero, if_true, if_false, fall_through); |
3987 } else { | 4004 } else { |
(...skipping 27 matching lines...) Expand all Loading... |
4015 context()->Plug(if_true, if_false); | 4032 context()->Plug(if_true, if_false); |
4016 return; | 4033 return; |
4017 } | 4034 } |
4018 | 4035 |
4019 VisitForStackValue(expr->left()); | 4036 VisitForStackValue(expr->left()); |
4020 switch (expr->op()) { | 4037 switch (expr->op()) { |
4021 case Token::IN: | 4038 case Token::IN: |
4022 VisitForStackValue(expr->right()); | 4039 VisitForStackValue(expr->right()); |
4023 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION); | 4040 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION); |
4024 PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); | 4041 PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); |
4025 __ cmp(eax, Factory::true_value()); | 4042 __ cmp(eax, isolate()->factory()->true_value()); |
4026 Split(equal, if_true, if_false, fall_through); | 4043 Split(equal, if_true, if_false, fall_through); |
4027 break; | 4044 break; |
4028 | 4045 |
4029 case Token::INSTANCEOF: { | 4046 case Token::INSTANCEOF: { |
4030 VisitForStackValue(expr->right()); | 4047 VisitForStackValue(expr->right()); |
4031 InstanceofStub stub(InstanceofStub::kNoFlags); | 4048 InstanceofStub stub(InstanceofStub::kNoFlags); |
4032 __ CallStub(&stub); | 4049 __ CallStub(&stub); |
4033 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); | 4050 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); |
4034 __ test(eax, Operand(eax)); | 4051 __ test(eax, Operand(eax)); |
4035 // The stub returns 0 for true. | 4052 // The stub returns 0 for true. |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4108 Label materialize_true, materialize_false; | 4125 Label materialize_true, materialize_false; |
4109 Label* if_true = NULL; | 4126 Label* if_true = NULL; |
4110 Label* if_false = NULL; | 4127 Label* if_false = NULL; |
4111 Label* fall_through = NULL; | 4128 Label* fall_through = NULL; |
4112 context()->PrepareTest(&materialize_true, &materialize_false, | 4129 context()->PrepareTest(&materialize_true, &materialize_false, |
4113 &if_true, &if_false, &fall_through); | 4130 &if_true, &if_false, &fall_through); |
4114 | 4131 |
4115 VisitForAccumulatorValue(expr->expression()); | 4132 VisitForAccumulatorValue(expr->expression()); |
4116 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); | 4133 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); |
4117 | 4134 |
4118 __ cmp(eax, Factory::null_value()); | 4135 __ cmp(eax, isolate()->factory()->null_value()); |
4119 if (expr->is_strict()) { | 4136 if (expr->is_strict()) { |
4120 Split(equal, if_true, if_false, fall_through); | 4137 Split(equal, if_true, if_false, fall_through); |
4121 } else { | 4138 } else { |
4122 __ j(equal, if_true); | 4139 __ j(equal, if_true); |
4123 __ cmp(eax, Factory::undefined_value()); | 4140 __ cmp(eax, isolate()->factory()->undefined_value()); |
4124 __ j(equal, if_true); | 4141 __ j(equal, if_true); |
4125 __ test(eax, Immediate(kSmiTagMask)); | 4142 __ test(eax, Immediate(kSmiTagMask)); |
4126 __ j(zero, if_false); | 4143 __ j(zero, if_false); |
4127 // It can be an undetectable object. | 4144 // It can be an undetectable object. |
4128 __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset)); | 4145 __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset)); |
4129 __ movzx_b(edx, FieldOperand(edx, Map::kBitFieldOffset)); | 4146 __ movzx_b(edx, FieldOperand(edx, Map::kBitFieldOffset)); |
4130 __ test(edx, Immediate(1 << Map::kIsUndetectable)); | 4147 __ test(edx, Immediate(1 << Map::kIsUndetectable)); |
4131 Split(not_zero, if_true, if_false, fall_through); | 4148 Split(not_zero, if_true, if_false, fall_through); |
4132 } | 4149 } |
4133 context()->Plug(if_true, if_false); | 4150 context()->Plug(if_true, if_false); |
(...skipping 14 matching lines...) Expand all Loading... |
4148 Register FullCodeGenerator::context_register() { | 4165 Register FullCodeGenerator::context_register() { |
4149 return esi; | 4166 return esi; |
4150 } | 4167 } |
4151 | 4168 |
4152 | 4169 |
4153 void FullCodeGenerator::EmitCallIC(Handle<Code> ic, RelocInfo::Mode mode) { | 4170 void FullCodeGenerator::EmitCallIC(Handle<Code> ic, RelocInfo::Mode mode) { |
4154 ASSERT(mode == RelocInfo::CODE_TARGET || | 4171 ASSERT(mode == RelocInfo::CODE_TARGET || |
4155 mode == RelocInfo::CODE_TARGET_CONTEXT); | 4172 mode == RelocInfo::CODE_TARGET_CONTEXT); |
4156 switch (ic->kind()) { | 4173 switch (ic->kind()) { |
4157 case Code::LOAD_IC: | 4174 case Code::LOAD_IC: |
4158 __ IncrementCounter(&Counters::named_load_full, 1); | 4175 __ IncrementCounter(isolate()->counters()->named_load_full(), 1); |
4159 break; | 4176 break; |
4160 case Code::KEYED_LOAD_IC: | 4177 case Code::KEYED_LOAD_IC: |
4161 __ IncrementCounter(&Counters::keyed_load_full, 1); | 4178 __ IncrementCounter(isolate()->counters()->keyed_load_full(), 1); |
4162 break; | 4179 break; |
4163 case Code::STORE_IC: | 4180 case Code::STORE_IC: |
4164 __ IncrementCounter(&Counters::named_store_full, 1); | 4181 __ IncrementCounter(isolate()->counters()->named_store_full(), 1); |
4165 break; | 4182 break; |
4166 case Code::KEYED_STORE_IC: | 4183 case Code::KEYED_STORE_IC: |
4167 __ IncrementCounter(&Counters::keyed_store_full, 1); | 4184 __ IncrementCounter(isolate()->counters()->keyed_store_full(), 1); |
4168 default: | 4185 default: |
4169 break; | 4186 break; |
4170 } | 4187 } |
4171 | 4188 |
4172 __ call(ic, mode); | 4189 __ call(ic, mode); |
4173 | 4190 |
4174 // Crankshaft doesn't need patching of inlined loads and stores. | 4191 // Crankshaft doesn't need patching of inlined loads and stores. |
4175 // When compiling the snapshot we need to produce code that works | 4192 // When compiling the snapshot we need to produce code that works |
4176 // with and without Crankshaft. | 4193 // with and without Crankshaft. |
4177 if (V8::UseCrankshaft() && !Serializer::enabled()) { | 4194 if (V8::UseCrankshaft() && !Serializer::enabled()) { |
(...skipping 13 matching lines...) Expand all Loading... |
4191 default: | 4208 default: |
4192 // Do nothing. | 4209 // Do nothing. |
4193 break; | 4210 break; |
4194 } | 4211 } |
4195 } | 4212 } |
4196 | 4213 |
4197 | 4214 |
4198 void FullCodeGenerator::EmitCallIC(Handle<Code> ic, JumpPatchSite* patch_site) { | 4215 void FullCodeGenerator::EmitCallIC(Handle<Code> ic, JumpPatchSite* patch_site) { |
4199 switch (ic->kind()) { | 4216 switch (ic->kind()) { |
4200 case Code::LOAD_IC: | 4217 case Code::LOAD_IC: |
4201 __ IncrementCounter(&Counters::named_load_full, 1); | 4218 __ IncrementCounter(COUNTERS->named_load_full(), 1); |
4202 break; | 4219 break; |
4203 case Code::KEYED_LOAD_IC: | 4220 case Code::KEYED_LOAD_IC: |
4204 __ IncrementCounter(&Counters::keyed_load_full, 1); | 4221 __ IncrementCounter(COUNTERS->keyed_load_full(), 1); |
4205 break; | 4222 break; |
4206 case Code::STORE_IC: | 4223 case Code::STORE_IC: |
4207 __ IncrementCounter(&Counters::named_store_full, 1); | 4224 __ IncrementCounter(COUNTERS->named_store_full(), 1); |
4208 break; | 4225 break; |
4209 case Code::KEYED_STORE_IC: | 4226 case Code::KEYED_STORE_IC: |
4210 __ IncrementCounter(&Counters::keyed_store_full, 1); | 4227 __ IncrementCounter(COUNTERS->keyed_store_full(), 1); |
4211 default: | 4228 default: |
4212 break; | 4229 break; |
4213 } | 4230 } |
4214 | 4231 |
4215 __ call(ic, RelocInfo::CODE_TARGET); | 4232 __ call(ic, RelocInfo::CODE_TARGET); |
4216 if (patch_site != NULL && patch_site->is_bound()) { | 4233 if (patch_site != NULL && patch_site->is_bound()) { |
4217 patch_site->EmitPatchInfo(); | 4234 patch_site->EmitPatchInfo(); |
4218 } else { | 4235 } else { |
4219 __ nop(); // Signals no inlined code. | 4236 __ nop(); // Signals no inlined code. |
4220 } | 4237 } |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4261 // And return. | 4278 // And return. |
4262 __ ret(0); | 4279 __ ret(0); |
4263 } | 4280 } |
4264 | 4281 |
4265 | 4282 |
4266 #undef __ | 4283 #undef __ |
4267 | 4284 |
4268 } } // namespace v8::internal | 4285 } } // namespace v8::internal |
4269 | 4286 |
4270 #endif // V8_TARGET_ARCH_IA32 | 4287 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |