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 |