OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
155 // Visit all the explicit declarations unless there is an illegal | 155 // Visit all the explicit declarations unless there is an illegal |
156 // redeclaration. | 156 // redeclaration. |
157 if (scope()->HasIllegalRedeclaration()) { | 157 if (scope()->HasIllegalRedeclaration()) { |
158 scope()->VisitIllegalRedeclaration(this); | 158 scope()->VisitIllegalRedeclaration(this); |
159 } else { | 159 } else { |
160 VisitDeclarations(scope()->declarations()); | 160 VisitDeclarations(scope()->declarations()); |
161 } | 161 } |
162 } | 162 } |
163 | 163 |
164 { Comment cmnt(masm_, "[ Stack check"); | 164 { Comment cmnt(masm_, "[ Stack check"); |
165 Label ok; | 165 NearLabel ok; |
166 ExternalReference stack_limit = | 166 ExternalReference stack_limit = |
167 ExternalReference::address_of_stack_limit(); | 167 ExternalReference::address_of_stack_limit(); |
168 __ cmp(esp, Operand::StaticVariable(stack_limit)); | 168 __ cmp(esp, Operand::StaticVariable(stack_limit)); |
169 __ j(above_equal, &ok, taken); | 169 __ j(above_equal, &ok, taken); |
170 StackCheckStub stub; | 170 StackCheckStub stub; |
171 __ CallStub(&stub); | 171 __ CallStub(&stub); |
172 __ bind(&ok); | 172 __ bind(&ok); |
173 } | 173 } |
174 | 174 |
175 if (FLAG_trace) { | 175 if (FLAG_trace) { |
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
396 Label* materialize_false) { | 396 Label* materialize_false) { |
397 switch (context) { | 397 switch (context) { |
398 case Expression::kUninitialized: | 398 case Expression::kUninitialized: |
399 | 399 |
400 case Expression::kEffect: | 400 case Expression::kEffect: |
401 ASSERT_EQ(materialize_true, materialize_false); | 401 ASSERT_EQ(materialize_true, materialize_false); |
402 __ bind(materialize_true); | 402 __ bind(materialize_true); |
403 break; | 403 break; |
404 | 404 |
405 case Expression::kValue: { | 405 case Expression::kValue: { |
406 Label done; | 406 NearLabel done; |
407 switch (location_) { | 407 switch (location_) { |
408 case kAccumulator: | 408 case kAccumulator: |
409 __ bind(materialize_true); | 409 __ bind(materialize_true); |
410 __ mov(result_register(), Factory::true_value()); | 410 __ mov(result_register(), Factory::true_value()); |
411 __ jmp(&done); | 411 __ jmp(&done); |
412 __ bind(materialize_false); | 412 __ bind(materialize_false); |
413 __ mov(result_register(), Factory::false_value()); | 413 __ mov(result_register(), Factory::false_value()); |
414 break; | 414 break; |
415 case kStack: | 415 case kStack: |
416 __ bind(materialize_true); | 416 __ bind(materialize_true); |
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
678 Comment cmnt(masm_, "[ Case comparison"); | 678 Comment cmnt(masm_, "[ Case comparison"); |
679 __ bind(&next_test); | 679 __ bind(&next_test); |
680 next_test.Unuse(); | 680 next_test.Unuse(); |
681 | 681 |
682 // Compile the label expression. | 682 // Compile the label expression. |
683 VisitForValue(clause->label(), kAccumulator); | 683 VisitForValue(clause->label(), kAccumulator); |
684 | 684 |
685 // Perform the comparison as if via '==='. | 685 // Perform the comparison as if via '==='. |
686 __ mov(edx, Operand(esp, 0)); // Switch value. | 686 __ mov(edx, Operand(esp, 0)); // Switch value. |
687 if (ShouldInlineSmiCase(Token::EQ_STRICT)) { | 687 if (ShouldInlineSmiCase(Token::EQ_STRICT)) { |
688 Label slow_case; | 688 NearLabel slow_case; |
689 __ mov(ecx, edx); | 689 __ mov(ecx, edx); |
690 __ or_(ecx, Operand(eax)); | 690 __ or_(ecx, Operand(eax)); |
691 __ test(ecx, Immediate(kSmiTagMask)); | 691 __ test(ecx, Immediate(kSmiTagMask)); |
692 __ j(not_zero, &slow_case, not_taken); | 692 __ j(not_zero, &slow_case, not_taken); |
693 __ cmp(edx, Operand(eax)); | 693 __ cmp(edx, Operand(eax)); |
694 __ j(not_equal, &next_test); | 694 __ j(not_equal, &next_test); |
695 __ Drop(1); // Switch value is no longer needed. | 695 __ Drop(1); // Switch value is no longer needed. |
696 __ jmp(clause->body_target()->entry_label()); | 696 __ jmp(clause->body_target()->entry_label()); |
697 __ bind(&slow_case); | 697 __ bind(&slow_case); |
698 } | 698 } |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
738 // Get the object to enumerate over. Both SpiderMonkey and JSC | 738 // Get the object to enumerate over. Both SpiderMonkey and JSC |
739 // ignore null and undefined in contrast to the specification; see | 739 // ignore null and undefined in contrast to the specification; see |
740 // ECMA-262 section 12.6.4. | 740 // ECMA-262 section 12.6.4. |
741 VisitForValue(stmt->enumerable(), kAccumulator); | 741 VisitForValue(stmt->enumerable(), kAccumulator); |
742 __ cmp(eax, Factory::undefined_value()); | 742 __ cmp(eax, Factory::undefined_value()); |
743 __ j(equal, &exit); | 743 __ j(equal, &exit); |
744 __ cmp(eax, Factory::null_value()); | 744 __ cmp(eax, Factory::null_value()); |
745 __ j(equal, &exit); | 745 __ j(equal, &exit); |
746 | 746 |
747 // Convert the object to a JS object. | 747 // Convert the object to a JS object. |
748 Label convert, done_convert; | 748 NearLabel convert, done_convert; |
749 __ test(eax, Immediate(kSmiTagMask)); | 749 __ test(eax, Immediate(kSmiTagMask)); |
750 __ j(zero, &convert); | 750 __ j(zero, &convert); |
751 __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, ecx); | 751 __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, ecx); |
752 __ j(above_equal, &done_convert); | 752 __ j(above_equal, &done_convert); |
753 __ bind(&convert); | 753 __ bind(&convert); |
754 __ push(eax); | 754 __ push(eax); |
755 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); | 755 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); |
756 __ bind(&done_convert); | 756 __ bind(&done_convert); |
757 __ push(eax); | 757 __ push(eax); |
758 | 758 |
(...skipping 20 matching lines...) Expand all Loading... |
779 __ j(equal, &call_runtime); | 779 __ j(equal, &call_runtime); |
780 | 780 |
781 // Check that there in an enum cache in the non-empty instance | 781 // Check that there in an enum cache in the non-empty instance |
782 // descriptors (edx). This is the case if the next enumeration | 782 // descriptors (edx). This is the case if the next enumeration |
783 // index field does not contain a smi. | 783 // index field does not contain a smi. |
784 __ mov(edx, FieldOperand(edx, DescriptorArray::kEnumerationIndexOffset)); | 784 __ mov(edx, FieldOperand(edx, DescriptorArray::kEnumerationIndexOffset)); |
785 __ test(edx, Immediate(kSmiTagMask)); | 785 __ test(edx, Immediate(kSmiTagMask)); |
786 __ j(zero, &call_runtime); | 786 __ j(zero, &call_runtime); |
787 | 787 |
788 // For all objects but the receiver, check that the cache is empty. | 788 // For all objects but the receiver, check that the cache is empty. |
789 Label check_prototype; | 789 NearLabel check_prototype; |
790 __ cmp(ecx, Operand(eax)); | 790 __ cmp(ecx, Operand(eax)); |
791 __ j(equal, &check_prototype); | 791 __ j(equal, &check_prototype); |
792 __ mov(edx, FieldOperand(edx, DescriptorArray::kEnumCacheBridgeCacheOffset)); | 792 __ mov(edx, FieldOperand(edx, DescriptorArray::kEnumCacheBridgeCacheOffset)); |
793 __ cmp(edx, Factory::empty_fixed_array()); | 793 __ cmp(edx, Factory::empty_fixed_array()); |
794 __ j(not_equal, &call_runtime); | 794 __ j(not_equal, &call_runtime); |
795 | 795 |
796 // Load the prototype from the map and loop if non-null. | 796 // Load the prototype from the map and loop if non-null. |
797 __ bind(&check_prototype); | 797 __ bind(&check_prototype); |
798 __ mov(ecx, FieldOperand(ebx, Map::kPrototypeOffset)); | 798 __ mov(ecx, FieldOperand(ebx, Map::kPrototypeOffset)); |
799 __ cmp(ecx, Factory::null_value()); | 799 __ cmp(ecx, Factory::null_value()); |
800 __ j(not_equal, &next); | 800 __ j(not_equal, &next); |
801 | 801 |
802 // The enum cache is valid. Load the map of the object being | 802 // The enum cache is valid. Load the map of the object being |
803 // iterated over and use the cache for the iteration. | 803 // iterated over and use the cache for the iteration. |
804 Label use_cache; | 804 NearLabel use_cache; |
805 __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset)); | 805 __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset)); |
806 __ jmp(&use_cache); | 806 __ jmp(&use_cache); |
807 | 807 |
808 // Get the set of properties to enumerate. | 808 // Get the set of properties to enumerate. |
809 __ bind(&call_runtime); | 809 __ bind(&call_runtime); |
810 __ push(eax); // Duplicate the enumerable object on the stack. | 810 __ push(eax); // Duplicate the enumerable object on the stack. |
811 __ CallRuntime(Runtime::kGetPropertyNamesFast, 1); | 811 __ CallRuntime(Runtime::kGetPropertyNamesFast, 1); |
812 | 812 |
813 // If we got a map from the runtime call, we can do a fast | 813 // If we got a map from the runtime call, we can do a fast |
814 // modification check. Otherwise, we got a fixed array, and we have | 814 // modification check. Otherwise, we got a fixed array, and we have |
815 // to do a slow check. | 815 // to do a slow check. |
816 Label fixed_array; | 816 NearLabel fixed_array; |
817 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), Factory::meta_map()); | 817 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), Factory::meta_map()); |
818 __ j(not_equal, &fixed_array); | 818 __ j(not_equal, &fixed_array); |
819 | 819 |
820 // We got a map in register eax. Get the enumeration cache from it. | 820 // We got a map in register eax. Get the enumeration cache from it. |
821 __ bind(&use_cache); | 821 __ bind(&use_cache); |
822 __ mov(ecx, FieldOperand(eax, Map::kInstanceDescriptorsOffset)); | 822 __ mov(ecx, FieldOperand(eax, Map::kInstanceDescriptorsOffset)); |
823 __ mov(ecx, FieldOperand(ecx, DescriptorArray::kEnumerationIndexOffset)); | 823 __ mov(ecx, FieldOperand(ecx, DescriptorArray::kEnumerationIndexOffset)); |
824 __ mov(edx, FieldOperand(ecx, DescriptorArray::kEnumCacheBridgeCacheOffset)); | 824 __ mov(edx, FieldOperand(ecx, DescriptorArray::kEnumCacheBridgeCacheOffset)); |
825 | 825 |
826 // Setup the four remaining stack slots. | 826 // Setup the four remaining stack slots. |
(...skipping 21 matching lines...) Expand all Loading... |
848 // Get the current entry of the array into register ebx. | 848 // Get the current entry of the array into register ebx. |
849 __ mov(ebx, Operand(esp, 2 * kPointerSize)); | 849 __ mov(ebx, Operand(esp, 2 * kPointerSize)); |
850 __ mov(ebx, FieldOperand(ebx, eax, times_2, FixedArray::kHeaderSize)); | 850 __ mov(ebx, FieldOperand(ebx, eax, times_2, FixedArray::kHeaderSize)); |
851 | 851 |
852 // Get the expected map from the stack or a zero map in the | 852 // Get the expected map from the stack or a zero map in the |
853 // permanent slow case into register edx. | 853 // permanent slow case into register edx. |
854 __ mov(edx, Operand(esp, 3 * kPointerSize)); | 854 __ mov(edx, Operand(esp, 3 * kPointerSize)); |
855 | 855 |
856 // Check if the expected map still matches that of the enumerable. | 856 // Check if the expected map still matches that of the enumerable. |
857 // If not, we have to filter the key. | 857 // If not, we have to filter the key. |
858 Label update_each; | 858 NearLabel update_each; |
859 __ mov(ecx, Operand(esp, 4 * kPointerSize)); | 859 __ mov(ecx, Operand(esp, 4 * kPointerSize)); |
860 __ cmp(edx, FieldOperand(ecx, HeapObject::kMapOffset)); | 860 __ cmp(edx, FieldOperand(ecx, HeapObject::kMapOffset)); |
861 __ j(equal, &update_each); | 861 __ j(equal, &update_each); |
862 | 862 |
863 // Convert the entry to a string or null if it isn't a property | 863 // Convert the entry to a string or null if it isn't a property |
864 // anymore. If the property has been removed while iterating, we | 864 // anymore. If the property has been removed while iterating, we |
865 // just skip it. | 865 // just skip it. |
866 __ push(ecx); // Enumerable. | 866 __ push(ecx); // Enumerable. |
867 __ push(ebx); // Current entry. | 867 __ push(ebx); // Current entry. |
868 __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION); | 868 __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION); |
869 __ test(eax, Operand(eax)); | 869 __ test(eax, Operand(eax)); |
870 __ j(equal, loop_statement.continue_target()); | 870 __ j(equal, loop_statement.continue_target()); |
871 __ mov(ebx, Operand(eax)); | 871 __ mov(ebx, Operand(eax)); |
872 | 872 |
873 // Update the 'each' property or variable from the possibly filtered | 873 // Update the 'each' property or variable from the possibly filtered |
874 // entry in register ebx. | 874 // entry in register ebx. |
875 __ bind(&update_each); | 875 __ bind(&update_each); |
876 __ mov(result_register(), ebx); | 876 __ mov(result_register(), ebx); |
877 // Perform the assignment as if via '='. | 877 // Perform the assignment as if via '='. |
878 EmitAssignment(stmt->each()); | 878 EmitAssignment(stmt->each()); |
879 | 879 |
880 // Generate code for the body of the loop. | 880 // Generate code for the body of the loop. |
881 Label stack_limit_hit, stack_check_done; | 881 Label stack_limit_hit; |
| 882 NearLabel stack_check_done; |
882 Visit(stmt->body()); | 883 Visit(stmt->body()); |
883 | 884 |
884 __ StackLimitCheck(&stack_limit_hit); | 885 __ StackLimitCheck(&stack_limit_hit); |
885 __ bind(&stack_check_done); | 886 __ bind(&stack_check_done); |
886 | 887 |
887 // Generate code for going to the next element by incrementing the | 888 // Generate code for going to the next element by incrementing the |
888 // index (smi) stored on top of the stack. | 889 // index (smi) stored on top of the stack. |
889 __ bind(loop_statement.continue_target()); | 890 __ bind(loop_statement.continue_target()); |
890 __ add(Operand(esp, 0 * kPointerSize), Immediate(Smi::FromInt(1))); | 891 __ add(Operand(esp, 0 * kPointerSize), Immediate(Smi::FromInt(1))); |
891 __ jmp(&loop); | 892 __ jmp(&loop); |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
953 // If no outer scope calls eval, we do not need to check more | 954 // If no outer scope calls eval, we do not need to check more |
954 // context extensions. If we have reached an eval scope, we check | 955 // context extensions. If we have reached an eval scope, we check |
955 // all extensions from this point. | 956 // all extensions from this point. |
956 if (!s->outer_scope_calls_eval() || s->is_eval_scope()) break; | 957 if (!s->outer_scope_calls_eval() || s->is_eval_scope()) break; |
957 s = s->outer_scope(); | 958 s = s->outer_scope(); |
958 } | 959 } |
959 | 960 |
960 if (s != NULL && s->is_eval_scope()) { | 961 if (s != NULL && s->is_eval_scope()) { |
961 // Loop up the context chain. There is no frame effect so it is | 962 // Loop up the context chain. There is no frame effect so it is |
962 // safe to use raw labels here. | 963 // safe to use raw labels here. |
963 Label next, fast; | 964 NearLabel next, fast; |
964 if (!context.is(temp)) { | 965 if (!context.is(temp)) { |
965 __ mov(temp, context); | 966 __ mov(temp, context); |
966 } | 967 } |
967 __ bind(&next); | 968 __ bind(&next); |
968 // Terminate at global context. | 969 // Terminate at global context. |
969 __ cmp(FieldOperand(temp, HeapObject::kMapOffset), | 970 __ cmp(FieldOperand(temp, HeapObject::kMapOffset), |
970 Immediate(Factory::global_context_map())); | 971 Immediate(Factory::global_context_map())); |
971 __ j(equal, &fast); | 972 __ j(equal, &fast); |
972 // Check that extension is NULL. | 973 // Check that extension is NULL. |
973 __ cmp(ContextOperand(temp, Context::EXTENSION_INDEX), Immediate(0)); | 974 __ cmp(ContextOperand(temp, Context::EXTENSION_INDEX), Immediate(0)); |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1112 | 1113 |
1113 Apply(context, eax); | 1114 Apply(context, eax); |
1114 | 1115 |
1115 } else if (slot != NULL) { | 1116 } else if (slot != NULL) { |
1116 Comment cmnt(masm_, (slot->type() == Slot::CONTEXT) | 1117 Comment cmnt(masm_, (slot->type() == Slot::CONTEXT) |
1117 ? "Context slot" | 1118 ? "Context slot" |
1118 : "Stack slot"); | 1119 : "Stack slot"); |
1119 if (var->mode() == Variable::CONST) { | 1120 if (var->mode() == Variable::CONST) { |
1120 // Constants may be the hole value if they have not been initialized. | 1121 // Constants may be the hole value if they have not been initialized. |
1121 // Unhole them. | 1122 // Unhole them. |
1122 Label done; | 1123 NearLabel done; |
1123 MemOperand slot_operand = EmitSlotSearch(slot, eax); | 1124 MemOperand slot_operand = EmitSlotSearch(slot, eax); |
1124 __ mov(eax, slot_operand); | 1125 __ mov(eax, slot_operand); |
1125 __ cmp(eax, Factory::the_hole_value()); | 1126 __ cmp(eax, Factory::the_hole_value()); |
1126 __ j(not_equal, &done); | 1127 __ j(not_equal, &done); |
1127 __ mov(eax, Factory::undefined_value()); | 1128 __ mov(eax, Factory::undefined_value()); |
1128 __ bind(&done); | 1129 __ bind(&done); |
1129 Apply(context, eax); | 1130 Apply(context, eax); |
1130 } else { | 1131 } else { |
1131 Apply(context, slot); | 1132 Apply(context, slot); |
1132 } | 1133 } |
(...skipping 28 matching lines...) Expand all Loading... |
1161 // call. It is treated specially by the LoadIC code. | 1162 // call. It is treated specially by the LoadIC code. |
1162 __ nop(); | 1163 __ nop(); |
1163 // Drop key and object left on the stack by IC. | 1164 // Drop key and object left on the stack by IC. |
1164 Apply(context, eax); | 1165 Apply(context, eax); |
1165 } | 1166 } |
1166 } | 1167 } |
1167 | 1168 |
1168 | 1169 |
1169 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { | 1170 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { |
1170 Comment cmnt(masm_, "[ RegExpLiteral"); | 1171 Comment cmnt(masm_, "[ RegExpLiteral"); |
1171 Label materialized; | 1172 NearLabel materialized; |
1172 // Registers will be used as follows: | 1173 // Registers will be used as follows: |
1173 // edi = JS function. | 1174 // edi = JS function. |
1174 // ecx = literals array. | 1175 // ecx = literals array. |
1175 // ebx = regexp literal. | 1176 // ebx = regexp literal. |
1176 // eax = regexp literal clone. | 1177 // eax = regexp literal clone. |
1177 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); | 1178 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
1178 __ mov(ecx, FieldOperand(edi, JSFunction::kLiteralsOffset)); | 1179 __ mov(ecx, FieldOperand(edi, JSFunction::kLiteralsOffset)); |
1179 int literal_offset = | 1180 int literal_offset = |
1180 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; | 1181 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; |
1181 __ mov(ebx, FieldOperand(ecx, literal_offset)); | 1182 __ mov(ebx, FieldOperand(ecx, literal_offset)); |
(...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1482 __ call(ic, RelocInfo::CODE_TARGET); | 1483 __ call(ic, RelocInfo::CODE_TARGET); |
1483 __ nop(); | 1484 __ nop(); |
1484 } | 1485 } |
1485 | 1486 |
1486 | 1487 |
1487 void FullCodeGenerator::EmitConstantSmiAdd(Expression* expr, | 1488 void FullCodeGenerator::EmitConstantSmiAdd(Expression* expr, |
1488 Expression::Context context, | 1489 Expression::Context context, |
1489 OverwriteMode mode, | 1490 OverwriteMode mode, |
1490 bool left_is_constant_smi, | 1491 bool left_is_constant_smi, |
1491 Smi* value) { | 1492 Smi* value) { |
1492 Label call_stub, done; | 1493 NearLabel call_stub; |
| 1494 Label done; |
1493 __ add(Operand(eax), Immediate(value)); | 1495 __ add(Operand(eax), Immediate(value)); |
1494 __ j(overflow, &call_stub); | 1496 __ j(overflow, &call_stub); |
1495 __ test(eax, Immediate(kSmiTagMask)); | 1497 __ test(eax, Immediate(kSmiTagMask)); |
1496 __ j(zero, &done); | 1498 __ j(zero, &done); |
1497 | 1499 |
1498 // Undo the optimistic add operation and call the shared stub. | 1500 // Undo the optimistic add operation and call the shared stub. |
1499 __ bind(&call_stub); | 1501 __ bind(&call_stub); |
1500 __ sub(Operand(eax), Immediate(value)); | 1502 __ sub(Operand(eax), Immediate(value)); |
1501 Token::Value op = Token::ADD; | 1503 Token::Value op = Token::ADD; |
1502 GenericBinaryOpStub stub(op, mode, NO_SMI_CODE_IN_STUB, TypeInfo::Unknown()); | 1504 GenericBinaryOpStub stub(op, mode, NO_SMI_CODE_IN_STUB, TypeInfo::Unknown()); |
(...skipping 1204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2707 __ CallStub(&stub); | 2709 __ CallStub(&stub); |
2708 Apply(context_, eax); | 2710 Apply(context_, eax); |
2709 } | 2711 } |
2710 | 2712 |
2711 | 2713 |
2712 void FullCodeGenerator::EmitValueOf(ZoneList<Expression*>* args) { | 2714 void FullCodeGenerator::EmitValueOf(ZoneList<Expression*>* args) { |
2713 ASSERT(args->length() == 1); | 2715 ASSERT(args->length() == 1); |
2714 | 2716 |
2715 VisitForValue(args->at(0), kAccumulator); // Load the object. | 2717 VisitForValue(args->at(0), kAccumulator); // Load the object. |
2716 | 2718 |
2717 Label done; | 2719 NearLabel done; |
2718 // If the object is a smi return the object. | 2720 // If the object is a smi return the object. |
2719 __ test(eax, Immediate(kSmiTagMask)); | 2721 __ test(eax, Immediate(kSmiTagMask)); |
2720 __ j(zero, &done); | 2722 __ j(zero, &done); |
2721 // If the object is not a value type, return the object. | 2723 // If the object is not a value type, return the object. |
2722 __ CmpObjectType(eax, JS_VALUE_TYPE, ebx); | 2724 __ CmpObjectType(eax, JS_VALUE_TYPE, ebx); |
2723 __ j(not_equal, &done); | 2725 __ j(not_equal, &done); |
2724 __ mov(eax, FieldOperand(eax, JSValue::kValueOffset)); | 2726 __ mov(eax, FieldOperand(eax, JSValue::kValueOffset)); |
2725 | 2727 |
2726 __ bind(&done); | 2728 __ bind(&done); |
2727 Apply(context_, eax); | 2729 Apply(context_, eax); |
(...skipping 10 matching lines...) Expand all Loading... |
2738 } | 2740 } |
2739 | 2741 |
2740 | 2742 |
2741 void FullCodeGenerator::EmitSetValueOf(ZoneList<Expression*>* args) { | 2743 void FullCodeGenerator::EmitSetValueOf(ZoneList<Expression*>* args) { |
2742 ASSERT(args->length() == 2); | 2744 ASSERT(args->length() == 2); |
2743 | 2745 |
2744 VisitForValue(args->at(0), kStack); // Load the object. | 2746 VisitForValue(args->at(0), kStack); // Load the object. |
2745 VisitForValue(args->at(1), kAccumulator); // Load the value. | 2747 VisitForValue(args->at(1), kAccumulator); // Load the value. |
2746 __ pop(ebx); // eax = value. ebx = object. | 2748 __ pop(ebx); // eax = value. ebx = object. |
2747 | 2749 |
2748 Label done; | 2750 NearLabel done; |
2749 // If the object is a smi, return the value. | 2751 // If the object is a smi, return the value. |
2750 __ test(ebx, Immediate(kSmiTagMask)); | 2752 __ test(ebx, Immediate(kSmiTagMask)); |
2751 __ j(zero, &done); | 2753 __ j(zero, &done); |
2752 | 2754 |
2753 // If the object is not a value type, return the value. | 2755 // If the object is not a value type, return the value. |
2754 __ CmpObjectType(ebx, JS_VALUE_TYPE, ecx); | 2756 __ CmpObjectType(ebx, JS_VALUE_TYPE, ecx); |
2755 __ j(not_equal, &done); | 2757 __ j(not_equal, &done); |
2756 | 2758 |
2757 // Store the value. | 2759 // Store the value. |
2758 __ mov(FieldOperand(ebx, JSValue::kValueOffset), eax); | 2760 __ mov(FieldOperand(ebx, JSValue::kValueOffset), eax); |
(...skipping 507 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3266 break; | 3268 break; |
3267 } | 3269 } |
3268 | 3270 |
3269 case Token::BIT_NOT: { | 3271 case Token::BIT_NOT: { |
3270 Comment cmt(masm_, "[ UnaryOperation (BIT_NOT)"); | 3272 Comment cmt(masm_, "[ UnaryOperation (BIT_NOT)"); |
3271 // The generic unary operation stub expects the argument to be | 3273 // The generic unary operation stub expects the argument to be |
3272 // in the accumulator register eax. | 3274 // in the accumulator register eax. |
3273 VisitForValue(expr->expression(), kAccumulator); | 3275 VisitForValue(expr->expression(), kAccumulator); |
3274 Label done; | 3276 Label done; |
3275 if (ShouldInlineSmiCase(expr->op())) { | 3277 if (ShouldInlineSmiCase(expr->op())) { |
3276 Label call_stub; | 3278 NearLabel call_stub; |
3277 __ test(eax, Immediate(kSmiTagMask)); | 3279 __ test(eax, Immediate(kSmiTagMask)); |
3278 __ j(not_zero, &call_stub); | 3280 __ j(not_zero, &call_stub); |
3279 __ lea(eax, Operand(eax, kSmiTagMask)); | 3281 __ lea(eax, Operand(eax, kSmiTagMask)); |
3280 __ not_(eax); | 3282 __ not_(eax); |
3281 __ jmp(&done); | 3283 __ jmp(&done); |
3282 __ bind(&call_stub); | 3284 __ bind(&call_stub); |
3283 } | 3285 } |
3284 bool overwrite = expr->expression()->ResultOverwriteAllowed(); | 3286 bool overwrite = expr->expression()->ResultOverwriteAllowed(); |
3285 UnaryOverwriteMode mode = | 3287 UnaryOverwriteMode mode = |
3286 overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE; | 3288 overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE; |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3341 } else { | 3343 } else { |
3342 VisitForValue(prop->obj(), kStack); | 3344 VisitForValue(prop->obj(), kStack); |
3343 VisitForValue(prop->key(), kAccumulator); | 3345 VisitForValue(prop->key(), kAccumulator); |
3344 __ mov(edx, Operand(esp, 0)); | 3346 __ mov(edx, Operand(esp, 0)); |
3345 __ push(eax); | 3347 __ push(eax); |
3346 EmitKeyedPropertyLoad(prop); | 3348 EmitKeyedPropertyLoad(prop); |
3347 } | 3349 } |
3348 } | 3350 } |
3349 | 3351 |
3350 // Call ToNumber only if operand is not a smi. | 3352 // Call ToNumber only if operand is not a smi. |
3351 Label no_conversion; | 3353 NearLabel no_conversion; |
3352 if (ShouldInlineSmiCase(expr->op())) { | 3354 if (ShouldInlineSmiCase(expr->op())) { |
3353 __ test(eax, Immediate(kSmiTagMask)); | 3355 __ test(eax, Immediate(kSmiTagMask)); |
3354 __ j(zero, &no_conversion); | 3356 __ j(zero, &no_conversion); |
3355 } | 3357 } |
3356 __ push(eax); | 3358 __ push(eax); |
3357 __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION); | 3359 __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION); |
3358 __ bind(&no_conversion); | 3360 __ bind(&no_conversion); |
3359 | 3361 |
3360 // Save result for postfix expressions. | 3362 // Save result for postfix expressions. |
3361 if (expr->is_postfix()) { | 3363 if (expr->is_postfix()) { |
(...skipping 17 matching lines...) Expand all Loading... |
3379 break; | 3381 break; |
3380 case KEYED_PROPERTY: | 3382 case KEYED_PROPERTY: |
3381 __ mov(Operand(esp, 2 * kPointerSize), eax); | 3383 __ mov(Operand(esp, 2 * kPointerSize), eax); |
3382 break; | 3384 break; |
3383 } | 3385 } |
3384 break; | 3386 break; |
3385 } | 3387 } |
3386 } | 3388 } |
3387 | 3389 |
3388 // Inline smi case if we are in a loop. | 3390 // Inline smi case if we are in a loop. |
3389 Label stub_call, done; | 3391 NearLabel stub_call; |
| 3392 Label done; |
3390 if (ShouldInlineSmiCase(expr->op())) { | 3393 if (ShouldInlineSmiCase(expr->op())) { |
3391 if (expr->op() == Token::INC) { | 3394 if (expr->op() == Token::INC) { |
3392 __ add(Operand(eax), Immediate(Smi::FromInt(1))); | 3395 __ add(Operand(eax), Immediate(Smi::FromInt(1))); |
3393 } else { | 3396 } else { |
3394 __ sub(Operand(eax), Immediate(Smi::FromInt(1))); | 3397 __ sub(Operand(eax), Immediate(Smi::FromInt(1))); |
3395 } | 3398 } |
3396 __ j(overflow, &stub_call); | 3399 __ j(overflow, &stub_call); |
3397 // We could eliminate this smi check if we split the code at | 3400 // We could eliminate this smi check if we split the code at |
3398 // the first smi check before calling ToNumber. | 3401 // the first smi check before calling ToNumber. |
3399 __ test(eax, Immediate(kSmiTagMask)); | 3402 __ test(eax, Immediate(kSmiTagMask)); |
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3666 cc = greater_equal; | 3669 cc = greater_equal; |
3667 __ pop(edx); | 3670 __ pop(edx); |
3668 break; | 3671 break; |
3669 case Token::IN: | 3672 case Token::IN: |
3670 case Token::INSTANCEOF: | 3673 case Token::INSTANCEOF: |
3671 default: | 3674 default: |
3672 UNREACHABLE(); | 3675 UNREACHABLE(); |
3673 } | 3676 } |
3674 | 3677 |
3675 if (ShouldInlineSmiCase(op)) { | 3678 if (ShouldInlineSmiCase(op)) { |
3676 Label slow_case; | 3679 NearLabel slow_case; |
3677 __ mov(ecx, Operand(edx)); | 3680 __ mov(ecx, Operand(edx)); |
3678 __ or_(ecx, Operand(eax)); | 3681 __ or_(ecx, Operand(eax)); |
3679 __ test(ecx, Immediate(kSmiTagMask)); | 3682 __ test(ecx, Immediate(kSmiTagMask)); |
3680 __ j(not_zero, &slow_case, not_taken); | 3683 __ j(not_zero, &slow_case, not_taken); |
3681 __ cmp(edx, Operand(eax)); | 3684 __ cmp(edx, Operand(eax)); |
3682 Split(cc, if_true, if_false, NULL); | 3685 Split(cc, if_true, if_false, NULL); |
3683 __ bind(&slow_case); | 3686 __ bind(&slow_case); |
3684 } | 3687 } |
3685 | 3688 |
3686 CompareStub stub(cc, strict); | 3689 CompareStub stub(cc, strict); |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3776 // And return. | 3779 // And return. |
3777 __ ret(0); | 3780 __ ret(0); |
3778 } | 3781 } |
3779 | 3782 |
3780 | 3783 |
3781 #undef __ | 3784 #undef __ |
3782 | 3785 |
3783 } } // namespace v8::internal | 3786 } } // namespace v8::internal |
3784 | 3787 |
3785 #endif // V8_TARGET_ARCH_IA32 | 3788 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |