| 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 788 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 799 // The variable in the decl always resides in the current context. | 799 // The variable in the decl always resides in the current context. |
| 800 ASSERT_EQ(0, scope()->ContextChainLength(variable->scope())); | 800 ASSERT_EQ(0, scope()->ContextChainLength(variable->scope())); |
| 801 if (FLAG_debug_code) { | 801 if (FLAG_debug_code) { |
| 802 // Check if we have the correct context pointer. | 802 // Check if we have the correct context pointer. |
| 803 __ mov(ebx, | 803 __ mov(ebx, |
| 804 CodeGenerator::ContextOperand(esi, Context::FCONTEXT_INDEX)); | 804 CodeGenerator::ContextOperand(esi, Context::FCONTEXT_INDEX)); |
| 805 __ cmp(ebx, Operand(esi)); | 805 __ cmp(ebx, Operand(esi)); |
| 806 __ Check(equal, "Unexpected declaration in current context."); | 806 __ Check(equal, "Unexpected declaration in current context."); |
| 807 } | 807 } |
| 808 if (mode == Variable::CONST) { | 808 if (mode == Variable::CONST) { |
| 809 __ mov(CodeGenerator::ContextOperand(esi, slot->index()), | 809 __ mov(eax, Immediate(Factory::the_hole_value())); |
| 810 Immediate(Factory::the_hole_value())); | 810 __ mov(CodeGenerator::ContextOperand(esi, slot->index()), eax); |
| 811 // No write barrier since the hole value is in old space. | 811 // No write barrier since the hole value is in old space. |
| 812 } else if (function != NULL) { | 812 } else if (function != NULL) { |
| 813 VisitForValue(function, kAccumulator); | 813 VisitForValue(function, kAccumulator); |
| 814 __ mov(CodeGenerator::ContextOperand(esi, slot->index()), | 814 __ mov(CodeGenerator::ContextOperand(esi, slot->index()), |
| 815 result_register()); | 815 result_register()); |
| 816 int offset = Context::SlotOffset(slot->index()); | 816 int offset = Context::SlotOffset(slot->index()); |
| 817 __ mov(ebx, esi); | 817 __ mov(ebx, esi); |
| 818 __ RecordWrite(ebx, offset, result_register(), ecx); | 818 __ RecordWrite(ebx, offset, result_register(), ecx); |
| 819 } | 819 } |
| 820 break; | 820 break; |
| 821 | 821 |
| 822 case Slot::LOOKUP: { | 822 case Slot::LOOKUP: { |
| 823 __ push(esi); | 823 __ push(esi); |
| 824 __ push(Immediate(variable->name())); | 824 __ push(Immediate(variable->name())); |
| 825 // Declaration nodes are always introduced in one of two modes. | 825 // Declaration nodes are always introduced in one of two modes. |
| 826 ASSERT(mode == Variable::VAR || mode == Variable::CONST); | 826 ASSERT(mode == Variable::VAR || |
| 827 PropertyAttributes attr = (mode == Variable::VAR) ? NONE : READ_ONLY; | 827 mode == Variable::CONST); |
| 828 PropertyAttributes attr = |
| 829 (mode == Variable::VAR) ? NONE : READ_ONLY; |
| 828 __ push(Immediate(Smi::FromInt(attr))); | 830 __ push(Immediate(Smi::FromInt(attr))); |
| 829 // Push initial value, if any. | 831 // Push initial value, if any. |
| 830 // Note: For variables we must not push an initial value (such as | 832 // Note: For variables we must not push an initial value (such as |
| 831 // 'undefined') because we may have a (legal) redeclaration and we | 833 // 'undefined') because we may have a (legal) redeclaration and we |
| 832 // must not destroy the current value. | 834 // must not destroy the current value. |
| 833 if (mode == Variable::CONST) { | 835 if (mode == Variable::CONST) { |
| 834 __ push(Immediate(Factory::the_hole_value())); | 836 __ push(Immediate(Factory::the_hole_value())); |
| 835 } else if (function != NULL) { | 837 } else if (function != NULL) { |
| 836 VisitForValue(function, kStack); | 838 VisitForValue(function, kStack); |
| 837 } else { | 839 } else { |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1002 | 1004 |
| 1003 // We got a map in register eax. Get the enumeration cache from it. | 1005 // We got a map in register eax. Get the enumeration cache from it. |
| 1004 __ mov(ecx, FieldOperand(eax, Map::kInstanceDescriptorsOffset)); | 1006 __ mov(ecx, FieldOperand(eax, Map::kInstanceDescriptorsOffset)); |
| 1005 __ mov(ecx, FieldOperand(ecx, DescriptorArray::kEnumerationIndexOffset)); | 1007 __ mov(ecx, FieldOperand(ecx, DescriptorArray::kEnumerationIndexOffset)); |
| 1006 __ mov(edx, FieldOperand(ecx, DescriptorArray::kEnumCacheBridgeCacheOffset)); | 1008 __ mov(edx, FieldOperand(ecx, DescriptorArray::kEnumCacheBridgeCacheOffset)); |
| 1007 | 1009 |
| 1008 // Setup the four remaining stack slots. | 1010 // Setup the four remaining stack slots. |
| 1009 __ push(eax); // Map. | 1011 __ push(eax); // Map. |
| 1010 __ push(edx); // Enumeration cache. | 1012 __ push(edx); // Enumeration cache. |
| 1011 __ mov(eax, FieldOperand(edx, FixedArray::kLengthOffset)); | 1013 __ mov(eax, FieldOperand(edx, FixedArray::kLengthOffset)); |
| 1014 __ SmiTag(eax); |
| 1012 __ push(eax); // Enumeration cache length (as smi). | 1015 __ push(eax); // Enumeration cache length (as smi). |
| 1013 __ push(Immediate(Smi::FromInt(0))); // Initial index. | 1016 __ push(Immediate(Smi::FromInt(0))); // Initial index. |
| 1014 __ jmp(&loop); | 1017 __ jmp(&loop); |
| 1015 | 1018 |
| 1016 // We got a fixed array in register eax. Iterate through that. | 1019 // We got a fixed array in register eax. Iterate through that. |
| 1017 __ bind(&fixed_array); | 1020 __ bind(&fixed_array); |
| 1018 __ push(Immediate(Smi::FromInt(0))); // Map (0) - force slow check. | 1021 __ push(Immediate(Smi::FromInt(0))); // Map (0) - force slow check. |
| 1019 __ push(eax); | 1022 __ push(eax); |
| 1020 __ mov(eax, FieldOperand(eax, FixedArray::kLengthOffset)); | 1023 __ mov(eax, FieldOperand(eax, FixedArray::kLengthOffset)); |
| 1024 __ SmiTag(eax); |
| 1021 __ push(eax); // Fixed array length (as smi). | 1025 __ push(eax); // Fixed array length (as smi). |
| 1022 __ push(Immediate(Smi::FromInt(0))); // Initial index. | 1026 __ push(Immediate(Smi::FromInt(0))); // Initial index. |
| 1023 | 1027 |
| 1024 // Generate code for doing the condition check. | 1028 // Generate code for doing the condition check. |
| 1025 __ bind(&loop); | 1029 __ bind(&loop); |
| 1026 __ mov(eax, Operand(esp, 0 * kPointerSize)); // Get the current index. | 1030 __ mov(eax, Operand(esp, 0 * kPointerSize)); // Get the current index. |
| 1027 __ cmp(eax, Operand(esp, 1 * kPointerSize)); // Compare to the array length. | 1031 __ cmp(eax, Operand(esp, 1 * kPointerSize)); // Compare to the array length. |
| 1028 __ j(above_equal, loop_statement.break_target()); | 1032 __ j(above_equal, loop_statement.break_target()); |
| 1029 | 1033 |
| 1030 // Get the current entry of the array into register ebx. | 1034 // Get the current entry of the array into register ebx. |
| (...skipping 28 matching lines...) Expand all Loading... |
| 1059 // Perform the assignment as if via '='. | 1063 // Perform the assignment as if via '='. |
| 1060 EmitAssignment(stmt->each()); | 1064 EmitAssignment(stmt->each()); |
| 1061 | 1065 |
| 1062 // Generate code for the body of the loop. | 1066 // Generate code for the body of the loop. |
| 1063 Label stack_limit_hit, stack_check_done; | 1067 Label stack_limit_hit, stack_check_done; |
| 1064 Visit(stmt->body()); | 1068 Visit(stmt->body()); |
| 1065 | 1069 |
| 1066 __ StackLimitCheck(&stack_limit_hit); | 1070 __ StackLimitCheck(&stack_limit_hit); |
| 1067 __ bind(&stack_check_done); | 1071 __ bind(&stack_check_done); |
| 1068 | 1072 |
| 1069 // Generate code for going to the next element by incrementing the | 1073 // Generate code for the going to the next element by incrementing |
| 1070 // index (smi) stored on top of the stack. | 1074 // the index (smi) stored on top of the stack. |
| 1071 __ bind(loop_statement.continue_target()); | 1075 __ bind(loop_statement.continue_target()); |
| 1072 __ add(Operand(esp, 0 * kPointerSize), Immediate(Smi::FromInt(1))); | 1076 __ add(Operand(esp, 0 * kPointerSize), Immediate(Smi::FromInt(1))); |
| 1073 __ jmp(&loop); | 1077 __ jmp(&loop); |
| 1074 | 1078 |
| 1075 // Slow case for the stack limit check. | 1079 // Slow case for the stack limit check. |
| 1076 StackCheckStub stack_check_stub; | 1080 StackCheckStub stack_check_stub; |
| 1077 __ bind(&stack_limit_hit); | 1081 __ bind(&stack_limit_hit); |
| 1078 __ CallStub(&stack_check_stub); | 1082 __ CallStub(&stack_check_stub); |
| 1079 __ jmp(&stack_check_done); | 1083 __ jmp(&stack_check_done); |
| 1080 | 1084 |
| (...skipping 941 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2022 __ j(zero, if_false); | 2026 __ j(zero, if_false); |
| 2023 __ cmp(eax, Factory::null_value()); | 2027 __ cmp(eax, Factory::null_value()); |
| 2024 __ j(equal, if_true); | 2028 __ j(equal, if_true); |
| 2025 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); | 2029 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); |
| 2026 // Undetectable objects behave like undefined when tested with typeof. | 2030 // Undetectable objects behave like undefined when tested with typeof. |
| 2027 __ movzx_b(ecx, FieldOperand(ebx, Map::kBitFieldOffset)); | 2031 __ movzx_b(ecx, FieldOperand(ebx, Map::kBitFieldOffset)); |
| 2028 __ test(ecx, Immediate(1 << Map::kIsUndetectable)); | 2032 __ test(ecx, Immediate(1 << Map::kIsUndetectable)); |
| 2029 __ j(not_zero, if_false); | 2033 __ j(not_zero, if_false); |
| 2030 __ movzx_b(ecx, FieldOperand(ebx, Map::kInstanceTypeOffset)); | 2034 __ movzx_b(ecx, FieldOperand(ebx, Map::kInstanceTypeOffset)); |
| 2031 __ cmp(ecx, FIRST_JS_OBJECT_TYPE); | 2035 __ cmp(ecx, FIRST_JS_OBJECT_TYPE); |
| 2032 __ j(below, if_false); | 2036 __ j(less, if_false); |
| 2033 __ cmp(ecx, LAST_JS_OBJECT_TYPE); | 2037 __ cmp(ecx, LAST_JS_OBJECT_TYPE); |
| 2034 __ j(below_equal, if_true); | 2038 __ j(less_equal, if_true); |
| 2035 __ jmp(if_false); | 2039 __ jmp(if_false); |
| 2036 | 2040 |
| 2037 Apply(context_, if_true, if_false); | 2041 Apply(context_, if_true, if_false); |
| 2038 } | 2042 } |
| 2039 | 2043 |
| 2040 | 2044 |
| 2041 void FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) { | 2045 void FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) { |
| 2042 ASSERT(args->length() == 1); | 2046 ASSERT(args->length() == 1); |
| 2043 | 2047 |
| 2044 VisitForValue(args->at(0), kAccumulator); | 2048 VisitForValue(args->at(0), kAccumulator); |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2216 | 2220 |
| 2217 // If the object is a smi, we return null. | 2221 // If the object is a smi, we return null. |
| 2218 __ test(eax, Immediate(kSmiTagMask)); | 2222 __ test(eax, Immediate(kSmiTagMask)); |
| 2219 __ j(zero, &null); | 2223 __ j(zero, &null); |
| 2220 | 2224 |
| 2221 // Check that the object is a JS object but take special care of JS | 2225 // Check that the object is a JS object but take special care of JS |
| 2222 // functions to make sure they have 'Function' as their class. | 2226 // functions to make sure they have 'Function' as their class. |
| 2223 __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset)); | 2227 __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset)); |
| 2224 __ movzx_b(ebx, FieldOperand(eax, Map::kInstanceTypeOffset)); | 2228 __ movzx_b(ebx, FieldOperand(eax, Map::kInstanceTypeOffset)); |
| 2225 __ cmp(ebx, FIRST_JS_OBJECT_TYPE); | 2229 __ cmp(ebx, FIRST_JS_OBJECT_TYPE); |
| 2226 __ j(below, &null); | 2230 __ j(less, &null); |
| 2227 | 2231 |
| 2228 // As long as JS_FUNCTION_TYPE is the last instance type and it is | 2232 // As long as JS_FUNCTION_TYPE is the last instance type and it is |
| 2229 // right after LAST_JS_OBJECT_TYPE, we can avoid checking for | 2233 // right after LAST_JS_OBJECT_TYPE, we can avoid checking for |
| 2230 // LAST_JS_OBJECT_TYPE. | 2234 // LAST_JS_OBJECT_TYPE. |
| 2231 ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); | 2235 ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); |
| 2232 ASSERT(JS_FUNCTION_TYPE == LAST_JS_OBJECT_TYPE + 1); | 2236 ASSERT(JS_FUNCTION_TYPE == LAST_JS_OBJECT_TYPE + 1); |
| 2233 __ cmp(ebx, JS_FUNCTION_TYPE); | 2237 __ cmp(ebx, JS_FUNCTION_TYPE); |
| 2234 __ j(equal, &function); | 2238 __ j(equal, &function); |
| 2235 | 2239 |
| 2236 // Check if the constructor in the map is a function. | 2240 // Check if the constructor in the map is a function. |
| (...skipping 999 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3236 // And return. | 3240 // And return. |
| 3237 __ ret(0); | 3241 __ ret(0); |
| 3238 } | 3242 } |
| 3239 | 3243 |
| 3240 | 3244 |
| 3241 #undef __ | 3245 #undef __ |
| 3242 | 3246 |
| 3243 } } // namespace v8::internal | 3247 } } // namespace v8::internal |
| 3244 | 3248 |
| 3245 #endif // V8_TARGET_ARCH_IA32 | 3249 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |