| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 916 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 927 // ECMA-262 section 12.6.4. | 927 // ECMA-262 section 12.6.4. |
| 928 VisitForAccumulatorValue(stmt->enumerable()); | 928 VisitForAccumulatorValue(stmt->enumerable()); |
| 929 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); | 929 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); |
| 930 __ cmp(r0, ip); | 930 __ cmp(r0, ip); |
| 931 __ b(eq, &exit); | 931 __ b(eq, &exit); |
| 932 Register null_value = r5; | 932 Register null_value = r5; |
| 933 __ LoadRoot(null_value, Heap::kNullValueRootIndex); | 933 __ LoadRoot(null_value, Heap::kNullValueRootIndex); |
| 934 __ cmp(r0, null_value); | 934 __ cmp(r0, null_value); |
| 935 __ b(eq, &exit); | 935 __ b(eq, &exit); |
| 936 | 936 |
| 937 PrepareForBailoutForId(stmt->PrepareId(), TOS_REG); |
| 938 |
| 937 // Convert the object to a JS object. | 939 // Convert the object to a JS object. |
| 938 Label convert, done_convert; | 940 Label convert, done_convert; |
| 939 __ JumpIfSmi(r0, &convert); | 941 __ JumpIfSmi(r0, &convert); |
| 940 __ CompareObjectType(r0, r1, r1, FIRST_SPEC_OBJECT_TYPE); | 942 __ CompareObjectType(r0, r1, r1, FIRST_SPEC_OBJECT_TYPE); |
| 941 __ b(ge, &done_convert); | 943 __ b(ge, &done_convert); |
| 942 __ bind(&convert); | 944 __ bind(&convert); |
| 943 __ push(r0); | 945 __ push(r0); |
| 944 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); | 946 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); |
| 945 __ bind(&done_convert); | 947 __ bind(&done_convert); |
| 946 __ push(r0); | 948 __ push(r0); |
| 947 | 949 |
| 948 // Check for proxies. | 950 // Check for proxies. |
| 949 Label call_runtime; | 951 Label call_runtime; |
| 950 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); | 952 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); |
| 951 __ CompareObjectType(r0, r1, r1, LAST_JS_PROXY_TYPE); | 953 __ CompareObjectType(r0, r1, r1, LAST_JS_PROXY_TYPE); |
| 952 __ b(le, &call_runtime); | 954 __ b(le, &call_runtime); |
| 953 | 955 |
| 954 // Check cache validity in generated code. This is a fast case for | 956 // Check cache validity in generated code. This is a fast case for |
| 955 // the JSObject::IsSimpleEnum cache validity checks. If we cannot | 957 // the JSObject::IsSimpleEnum cache validity checks. If we cannot |
| 956 // guarantee cache validity, call the runtime system to check cache | 958 // guarantee cache validity, call the runtime system to check cache |
| 957 // validity or get the property names in a fixed array. | 959 // validity or get the property names in a fixed array. |
| 958 Label next; | 960 __ CheckEnumCache(null_value, &call_runtime); |
| 959 // Preload a couple of values used in the loop. | |
| 960 Register empty_fixed_array_value = r6; | |
| 961 __ LoadRoot(empty_fixed_array_value, Heap::kEmptyFixedArrayRootIndex); | |
| 962 Register empty_descriptor_array_value = r7; | |
| 963 __ LoadRoot(empty_descriptor_array_value, | |
| 964 Heap::kEmptyDescriptorArrayRootIndex); | |
| 965 __ mov(r1, r0); | |
| 966 __ bind(&next); | |
| 967 | |
| 968 // Check that there are no elements. Register r1 contains the | |
| 969 // current JS object we've reached through the prototype chain. | |
| 970 __ ldr(r2, FieldMemOperand(r1, JSObject::kElementsOffset)); | |
| 971 __ cmp(r2, empty_fixed_array_value); | |
| 972 __ b(ne, &call_runtime); | |
| 973 | |
| 974 // Check that instance descriptors are not empty so that we can | |
| 975 // check for an enum cache. Leave the map in r2 for the subsequent | |
| 976 // prototype load. | |
| 977 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset)); | |
| 978 __ ldr(r3, FieldMemOperand(r2, Map::kInstanceDescriptorsOrBitField3Offset)); | |
| 979 __ JumpIfSmi(r3, &call_runtime); | |
| 980 | |
| 981 // Check that there is an enum cache in the non-empty instance | |
| 982 // descriptors (r3). This is the case if the next enumeration | |
| 983 // index field does not contain a smi. | |
| 984 __ ldr(r3, FieldMemOperand(r3, DescriptorArray::kEnumerationIndexOffset)); | |
| 985 __ JumpIfSmi(r3, &call_runtime); | |
| 986 | |
| 987 // For all objects but the receiver, check that the cache is empty. | |
| 988 Label check_prototype; | |
| 989 __ cmp(r1, r0); | |
| 990 __ b(eq, &check_prototype); | |
| 991 __ ldr(r3, FieldMemOperand(r3, DescriptorArray::kEnumCacheBridgeCacheOffset)); | |
| 992 __ cmp(r3, empty_fixed_array_value); | |
| 993 __ b(ne, &call_runtime); | |
| 994 | |
| 995 // Load the prototype from the map and loop if non-null. | |
| 996 __ bind(&check_prototype); | |
| 997 __ ldr(r1, FieldMemOperand(r2, Map::kPrototypeOffset)); | |
| 998 __ cmp(r1, null_value); | |
| 999 __ b(ne, &next); | |
| 1000 | 961 |
| 1001 // The enum cache is valid. Load the map of the object being | 962 // The enum cache is valid. Load the map of the object being |
| 1002 // iterated over and use the cache for the iteration. | 963 // iterated over and use the cache for the iteration. |
| 1003 Label use_cache; | 964 Label use_cache; |
| 1004 __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset)); | 965 __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset)); |
| 1005 __ b(&use_cache); | 966 __ b(&use_cache); |
| 1006 | 967 |
| 1007 // Get the set of properties to enumerate. | 968 // Get the set of properties to enumerate. |
| 1008 __ bind(&call_runtime); | 969 __ bind(&call_runtime); |
| 1009 __ push(r0); // Duplicate the enumerable object on the stack. | 970 __ push(r0); // Duplicate the enumerable object on the stack. |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1042 __ CompareObjectType(r2, r3, r3, LAST_JS_PROXY_TYPE); | 1003 __ CompareObjectType(r2, r3, r3, LAST_JS_PROXY_TYPE); |
| 1043 __ b(gt, &non_proxy); | 1004 __ b(gt, &non_proxy); |
| 1044 __ mov(r1, Operand(Smi::FromInt(0))); // Zero indicates proxy | 1005 __ mov(r1, Operand(Smi::FromInt(0))); // Zero indicates proxy |
| 1045 __ bind(&non_proxy); | 1006 __ bind(&non_proxy); |
| 1046 __ Push(r1, r0); // Smi and array | 1007 __ Push(r1, r0); // Smi and array |
| 1047 __ ldr(r1, FieldMemOperand(r0, FixedArray::kLengthOffset)); | 1008 __ ldr(r1, FieldMemOperand(r0, FixedArray::kLengthOffset)); |
| 1048 __ mov(r0, Operand(Smi::FromInt(0))); | 1009 __ mov(r0, Operand(Smi::FromInt(0))); |
| 1049 __ Push(r1, r0); // Fixed array length (as smi) and initial index. | 1010 __ Push(r1, r0); // Fixed array length (as smi) and initial index. |
| 1050 | 1011 |
| 1051 // Generate code for doing the condition check. | 1012 // Generate code for doing the condition check. |
| 1013 PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS); |
| 1052 __ bind(&loop); | 1014 __ bind(&loop); |
| 1053 // Load the current count to r0, load the length to r1. | 1015 // Load the current count to r0, load the length to r1. |
| 1054 __ Ldrd(r0, r1, MemOperand(sp, 0 * kPointerSize)); | 1016 __ Ldrd(r0, r1, MemOperand(sp, 0 * kPointerSize)); |
| 1055 __ cmp(r0, r1); // Compare to the array length. | 1017 __ cmp(r0, r1); // Compare to the array length. |
| 1056 __ b(hs, loop_statement.break_label()); | 1018 __ b(hs, loop_statement.break_label()); |
| 1057 | 1019 |
| 1058 // Get the current entry of the array into register r3. | 1020 // Get the current entry of the array into register r3. |
| 1059 __ ldr(r2, MemOperand(sp, 2 * kPointerSize)); | 1021 __ ldr(r2, MemOperand(sp, 2 * kPointerSize)); |
| 1060 __ add(r2, r2, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); | 1022 __ add(r2, r2, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
| 1061 __ ldr(r3, MemOperand(r2, r0, LSL, kPointerSizeLog2 - kSmiTagSize)); | 1023 __ ldr(r3, MemOperand(r2, r0, LSL, kPointerSizeLog2 - kSmiTagSize)); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1085 __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION); | 1047 __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION); |
| 1086 __ mov(r3, Operand(r0), SetCC); | 1048 __ mov(r3, Operand(r0), SetCC); |
| 1087 __ b(eq, loop_statement.continue_label()); | 1049 __ b(eq, loop_statement.continue_label()); |
| 1088 | 1050 |
| 1089 // Update the 'each' property or variable from the possibly filtered | 1051 // Update the 'each' property or variable from the possibly filtered |
| 1090 // entry in register r3. | 1052 // entry in register r3. |
| 1091 __ bind(&update_each); | 1053 __ bind(&update_each); |
| 1092 __ mov(result_register(), r3); | 1054 __ mov(result_register(), r3); |
| 1093 // Perform the assignment as if via '='. | 1055 // Perform the assignment as if via '='. |
| 1094 { EffectContext context(this); | 1056 { EffectContext context(this); |
| 1095 EmitAssignment(stmt->each(), stmt->AssignmentId()); | 1057 EmitAssignment(stmt->each()); |
| 1096 } | 1058 } |
| 1097 | 1059 |
| 1098 // Generate code for the body of the loop. | 1060 // Generate code for the body of the loop. |
| 1099 Visit(stmt->body()); | 1061 Visit(stmt->body()); |
| 1100 | 1062 |
| 1101 // Generate code for the going to the next element by incrementing | 1063 // Generate code for the going to the next element by incrementing |
| 1102 // the index (smi) stored on top of the stack. | 1064 // the index (smi) stored on top of the stack. |
| 1103 __ bind(loop_statement.continue_label()); | 1065 __ bind(loop_statement.continue_label()); |
| 1104 __ pop(r0); | 1066 __ pop(r0); |
| 1105 __ add(r0, r0, Operand(Smi::FromInt(1))); | 1067 __ add(r0, r0, Operand(Smi::FromInt(1))); |
| 1106 __ push(r0); | 1068 __ push(r0); |
| 1107 | 1069 |
| 1108 EmitStackCheck(stmt, &loop); | 1070 EmitStackCheck(stmt, &loop); |
| 1109 __ b(&loop); | 1071 __ b(&loop); |
| 1110 | 1072 |
| 1111 // Remove the pointers stored on the stack. | 1073 // Remove the pointers stored on the stack. |
| 1112 __ bind(loop_statement.break_label()); | 1074 __ bind(loop_statement.break_label()); |
| 1113 __ Drop(5); | 1075 __ Drop(5); |
| 1114 | 1076 |
| 1115 // Exit and decrement the loop depth. | 1077 // Exit and decrement the loop depth. |
| 1078 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); |
| 1116 __ bind(&exit); | 1079 __ bind(&exit); |
| 1117 decrement_loop_depth(); | 1080 decrement_loop_depth(); |
| 1118 } | 1081 } |
| 1119 | 1082 |
| 1120 | 1083 |
| 1121 void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info, | 1084 void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info, |
| 1122 bool pretenure) { | 1085 bool pretenure) { |
| 1123 // Use the fast case closure allocation code that allocates in new | 1086 // Use the fast case closure allocation code that allocates in new |
| 1124 // space for nested functions that don't need literals cloning. If | 1087 // space for nested functions that don't need literals cloning. If |
| 1125 // we're running with the --always-opt or the --prepare-always-opt | 1088 // we're running with the --always-opt or the --prepare-always-opt |
| (...skipping 741 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1867 OverwriteMode mode) { | 1830 OverwriteMode mode) { |
| 1868 __ pop(r1); | 1831 __ pop(r1); |
| 1869 BinaryOpStub stub(op, mode); | 1832 BinaryOpStub stub(op, mode); |
| 1870 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. | 1833 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. |
| 1871 __ Call(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id()); | 1834 __ Call(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id()); |
| 1872 patch_site.EmitPatchInfo(); | 1835 patch_site.EmitPatchInfo(); |
| 1873 context()->Plug(r0); | 1836 context()->Plug(r0); |
| 1874 } | 1837 } |
| 1875 | 1838 |
| 1876 | 1839 |
| 1877 void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) { | 1840 void FullCodeGenerator::EmitAssignment(Expression* expr) { |
| 1878 // Invalid left-hand sides are rewritten to have a 'throw | 1841 // Invalid left-hand sides are rewritten to have a 'throw |
| 1879 // ReferenceError' on the left-hand side. | 1842 // ReferenceError' on the left-hand side. |
| 1880 if (!expr->IsValidLeftHandSide()) { | 1843 if (!expr->IsValidLeftHandSide()) { |
| 1881 VisitForEffect(expr); | 1844 VisitForEffect(expr); |
| 1882 return; | 1845 return; |
| 1883 } | 1846 } |
| 1884 | 1847 |
| 1885 // Left-hand side can only be a property, a global or a (parameter or local) | 1848 // Left-hand side can only be a property, a global or a (parameter or local) |
| 1886 // slot. | 1849 // slot. |
| 1887 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; | 1850 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1919 __ mov(r1, r0); | 1882 __ mov(r1, r0); |
| 1920 __ pop(r2); | 1883 __ pop(r2); |
| 1921 __ pop(r0); // Restore value. | 1884 __ pop(r0); // Restore value. |
| 1922 Handle<Code> ic = is_classic_mode() | 1885 Handle<Code> ic = is_classic_mode() |
| 1923 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 1886 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
| 1924 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 1887 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
| 1925 __ Call(ic); | 1888 __ Call(ic); |
| 1926 break; | 1889 break; |
| 1927 } | 1890 } |
| 1928 } | 1891 } |
| 1929 PrepareForBailoutForId(bailout_ast_id, TOS_REG); | |
| 1930 context()->Plug(r0); | 1892 context()->Plug(r0); |
| 1931 } | 1893 } |
| 1932 | 1894 |
| 1933 | 1895 |
| 1934 void FullCodeGenerator::EmitVariableAssignment(Variable* var, | 1896 void FullCodeGenerator::EmitVariableAssignment(Variable* var, |
| 1935 Token::Value op) { | 1897 Token::Value op) { |
| 1936 if (var->IsUnallocated()) { | 1898 if (var->IsUnallocated()) { |
| 1937 // Global var, const, or let. | 1899 // Global var, const, or let. |
| 1938 __ mov(r2, Operand(var->name())); | 1900 __ mov(r2, Operand(var->name())); |
| 1939 __ ldr(r1, GlobalObjectOperand()); | 1901 __ ldr(r1, GlobalObjectOperand()); |
| (...skipping 2479 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4419 *context_length = 0; | 4381 *context_length = 0; |
| 4420 return previous_; | 4382 return previous_; |
| 4421 } | 4383 } |
| 4422 | 4384 |
| 4423 | 4385 |
| 4424 #undef __ | 4386 #undef __ |
| 4425 | 4387 |
| 4426 } } // namespace v8::internal | 4388 } } // namespace v8::internal |
| 4427 | 4389 |
| 4428 #endif // V8_TARGET_ARCH_ARM | 4390 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |