Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: src/arm/stub-cache-arm.cc

Issue 2860049: Port prototype-call-stubs for normal objects (http://codereview.chromium.org/... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/arm/macro-assembler-arm.cc ('k') | src/ia32/stub-cache-ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. 1 // Copyright 2006-2009 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 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
76 // Jump to the first instruction in the code stub. 76 // Jump to the first instruction in the code stub.
77 __ add(offset, offset, Operand(Code::kHeaderSize - kHeapObjectTag)); 77 __ add(offset, offset, Operand(Code::kHeaderSize - kHeapObjectTag));
78 __ Jump(offset); 78 __ Jump(offset);
79 79
80 // Miss: Restore offset and fall through. 80 // Miss: Restore offset and fall through.
81 __ bind(&miss); 81 __ bind(&miss);
82 __ pop(offset); 82 __ pop(offset);
83 } 83 }
84 84
85 85
86 // Helper function used to check that the dictionary doesn't contain
87 // the property. This function may return false negatives, so miss_label
88 // must always call a backup property check that is complete.
89 // This function is safe to call if the receiver has fast properties.
90 // Name must be a symbol and receiver must be a heap object.
91 static void GenerateDictionaryNegativeLookup(MacroAssembler* masm,
92 Label* miss_label,
93 Register receiver,
94 String* name,
95 Register r0,
96 Register extra) {
97 ASSERT(name->IsSymbol());
98 if (!extra.is(no_reg)) {
99 __ IncrementCounter(&Counters::negative_lookups, 1, r0, extra);
100 __ IncrementCounter(&Counters::negative_lookups_miss, 1, r0, extra);
101 }
102
103 Label done;
104
105 const int kInterceptorOrAccessCheckNeededMask =
106 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded);
107
108 // Bail out if the receiver has a named interceptor or requires access checks.
109 Register map = extra.is(no_reg) ? r0 : extra;
110 __ ldr(map, FieldMemOperand(receiver, HeapObject::kMapOffset));
111 __ ldrb(r0, FieldMemOperand(map, Map::kBitFieldOffset));
112 __ tst(r0, Operand(kInterceptorOrAccessCheckNeededMask));
113 __ b(ne, miss_label);
114
115 // Check that receiver is a JSObject.
116 if (extra.is(no_reg)) {
117 __ ldr(map, FieldMemOperand(receiver, HeapObject::kMapOffset));
118 }
119 __ ldrb(r0, FieldMemOperand(map, Map::kInstanceTypeOffset));
120 __ cmp(r0, Operand(FIRST_JS_OBJECT_TYPE));
121 __ b(lt, miss_label);
122
123 // Load properties array.
124 Register properties = r0;
125 __ ldr(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
126 // Check that the properties array is a dictionary.
127 if (!extra.is(no_reg)) {
128 __ ldr(extra, FieldMemOperand(properties, HeapObject::kMapOffset));
129 Register tmp = properties;
130 __ LoadRoot(tmp, Heap::kHashTableMapRootIndex);
131 __ cmp(extra, tmp);
132 } else {
133 Register tmp1 = receiver;
134 Register tmp2 = properties;
135 __ push(tmp1);
136 __ ldr(tmp1, FieldMemOperand(properties, HeapObject::kMapOffset));
137 __ LoadRoot(tmp2, Heap::kHashTableMapRootIndex);
138 __ cmp(tmp1, tmp2);
139 __ pop(tmp1);
140 }
141 __ b(ne, miss_label);
142
143 // Restore the temporarily used register.
144 __ ldr(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
145
146 // Compute the capacity mask.
147 const int kCapacityOffset =
148 StringDictionary::kHeaderSize +
149 StringDictionary::kCapacityIndex * kPointerSize;
150
151 // Generate an unrolled loop that performs a few probes before
152 // giving up.
153 static const int kProbes = 4;
154 const int kElementsStartOffset =
155 StringDictionary::kHeaderSize +
156 StringDictionary::kElementsStartIndex * kPointerSize;
157
158 // If names of slots in range from 1 to kProbes - 1 for the hash value are
159 // not equal to the name and kProbes-th slot is not used (its name is the
160 // undefined value), it guarantees the hash table doesn't contain the
161 // property. It's true even if some slots represent deleted properties
162 // (their names are the null value).
163 for (int i = 0; i < kProbes; i++) {
164 // r0 points to properties hash.
165 // Compute the masked index: (hash + i + i * i) & mask.
166 if (extra.is(no_reg)) {
167 __ push(receiver);
168 }
169 Register index = extra.is(no_reg) ? receiver : extra;
170 // Capacity is smi 2^n.
171 __ ldr(index, FieldMemOperand(properties, kCapacityOffset));
172 __ sub(index, index, Operand(1));
173 __ and_(index, index, Operand(
174 Smi::FromInt(name->Hash() + StringDictionary::GetProbeOffset(i))));
175
176 // Scale the index by multiplying by the entry size.
177 ASSERT(StringDictionary::kEntrySize == 3);
178 __ add(index, index, Operand(index, LSL, 1)); // index *= 3.
179
180 Register entity_name = extra.is(no_reg) ? properties : extra;
181 // Having undefined at this place means the name is not contained.
182 ASSERT_EQ(kSmiTagSize, 1);
183 Register tmp = extra.is(no_reg) ? receiver : properties;
184 __ add(tmp, properties, Operand(index, LSL, 1));
185 __ ldr(entity_name, FieldMemOperand(tmp, kElementsStartOffset));
186
187 ASSERT(!tmp.is(entity_name));
188 __ LoadRoot(tmp, Heap::kUndefinedValueRootIndex);
189 __ cmp(entity_name, tmp);
190 if (extra.is(no_reg)) {
191 // 'receiver' shares a register with 'entity_name'.
192 __ pop(receiver);
193 }
194 if (i != kProbes - 1) {
195 __ b(eq, &done);
196
197 // Stop if found the property.
198 __ cmp(entity_name, Operand(Handle<String>(name)));
199 __ b(eq, miss_label);
200
201 // Restore the properties.
202 __ ldr(properties,
203 FieldMemOperand(receiver, JSObject::kPropertiesOffset));
204 } else {
205 // Give up probing if still not found the undefined value.
206 __ b(ne, miss_label);
207 }
208 }
209 __ bind(&done);
210 if (!extra.is(no_reg)) {
211 __ DecrementCounter(&Counters::negative_lookups_miss, 1, r0, extra);
212 }
213 }
214
215
86 void StubCache::GenerateProbe(MacroAssembler* masm, 216 void StubCache::GenerateProbe(MacroAssembler* masm,
87 Code::Flags flags, 217 Code::Flags flags,
88 Register receiver, 218 Register receiver,
89 Register name, 219 Register name,
90 Register scratch, 220 Register scratch,
91 Register extra) { 221 Register extra) {
92 Label miss; 222 Label miss;
93 223
94 // Make sure that code is valid. The shifting code relies on the 224 // Make sure that code is valid. The shifting code relies on the
95 // entry size being 8. 225 // entry size being 8.
(...skipping 640 matching lines...) Expand 10 before | Expand all | Expand 10 after
736 866
737 Register StubCompiler::CheckPrototypes(JSObject* object, 867 Register StubCompiler::CheckPrototypes(JSObject* object,
738 Register object_reg, 868 Register object_reg,
739 JSObject* holder, 869 JSObject* holder,
740 Register holder_reg, 870 Register holder_reg,
741 Register scratch, 871 Register scratch,
742 String* name, 872 String* name,
743 int save_at_depth, 873 int save_at_depth,
744 Label* miss, 874 Label* miss,
745 Register extra) { 875 Register extra) {
746 // Check that the maps haven't changed. 876 // Make sure there's no overlap between scratch and the other
747 Register result = 877 // registers.
748 masm()->CheckMaps(object, object_reg, holder, holder_reg, scratch, 878 ASSERT(!scratch.is(object_reg) && !scratch.is(holder_reg));
749 save_at_depth, miss); 879
880 // Keep track of the current object in register reg.
881 Register reg = object_reg;
882 int depth = 0;
883
884 if (save_at_depth == depth) {
885 __ str(reg, MemOperand(sp));
886 }
887
888 // Check the maps in the prototype chain.
889 // Traverse the prototype chain from the object and do map checks.
890 JSObject* current = object;
891 while (current != holder) {
892 depth++;
893
894 // Only global objects and objects that do not require access
895 // checks are allowed in stubs.
896 ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded());
897
898 JSObject* prototype = JSObject::cast(current->GetPrototype());
899 if (!current->HasFastProperties() &&
900 !current->IsJSGlobalObject() &&
901 !current->IsJSGlobalProxy()) {
902 if (!name->IsSymbol()) {
903 Object* lookup_result = Heap::LookupSymbol(name);
904 if (lookup_result->IsFailure()) {
905 set_failure(Failure::cast(lookup_result));
906 return reg;
907 } else {
908 name = String::cast(lookup_result);
909 }
910 }
911 ASSERT(current->property_dictionary()->FindEntry(name) ==
912 StringDictionary::kNotFound);
913
914 GenerateDictionaryNegativeLookup(masm(),
915 miss,
916 reg,
917 name,
918 scratch,
919 extra);
920 __ ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset));
921 reg = holder_reg; // from now the object is in holder_reg
922 __ ldr(reg, FieldMemOperand(scratch, Map::kPrototypeOffset));
923 } else {
924 // Get the map of the current object.
925 __ ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset));
926 __ cmp(scratch, Operand(Handle<Map>(current->map())));
927
928 // Branch on the result of the map check.
929 __ b(ne, miss);
930
931 // Check access rights to the global object. This has to happen
932 // after the map check so that we know that the object is
933 // actually a global object.
934 if (current->IsJSGlobalProxy()) {
935 __ CheckAccessGlobalProxy(reg, scratch, miss);
936 // Restore scratch register to be the map of the object. In the
937 // new space case below, we load the prototype from the map in
938 // the scratch register.
939 __ ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset));
940 }
941
942 reg = holder_reg; // from now the object is in holder_reg
943 if (Heap::InNewSpace(prototype)) {
944 // The prototype is in new space; we cannot store a reference
945 // to it in the code. Load it from the map.
946 __ ldr(reg, FieldMemOperand(scratch, Map::kPrototypeOffset));
947 } else {
948 // The prototype is in old space; load it directly.
949 __ mov(reg, Operand(Handle<JSObject>(prototype)));
950 }
951 }
952
953 if (save_at_depth == depth) {
954 __ str(reg, MemOperand(sp));
955 }
956
957 // Go to the next object in the prototype chain.
958 current = prototype;
959 }
960
961 // Check the holder map.
962 __ ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset));
963 __ cmp(scratch, Operand(Handle<Map>(current->map())));
964 __ b(ne, miss);
965
966 // Log the check depth.
967 LOG(IntEvent("check-maps-depth", depth + 1));
968
969 // Perform security check for access to the global object and return
970 // the holder register.
971 ASSERT(current == holder);
972 ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded());
973 if (current->IsJSGlobalProxy()) {
974 __ CheckAccessGlobalProxy(reg, scratch, miss);
975 }
750 976
751 // If we've skipped any global objects, it's not enough to verify 977 // If we've skipped any global objects, it's not enough to verify
752 // that their maps haven't changed. We also need to check that the 978 // that their maps haven't changed. We also need to check that the
753 // property cell for the property is still empty. 979 // property cell for the property is still empty.
754 while (object != holder) { 980 current = object;
755 if (object->IsGlobalObject()) { 981 while (current != holder) {
982 if (current->IsGlobalObject()) {
756 Object* cell = GenerateCheckPropertyCell(masm(), 983 Object* cell = GenerateCheckPropertyCell(masm(),
757 GlobalObject::cast(object), 984 GlobalObject::cast(current),
758 name, 985 name,
759 scratch, 986 scratch,
760 miss); 987 miss);
761 if (cell->IsFailure()) { 988 if (cell->IsFailure()) {
762 set_failure(Failure::cast(cell)); 989 set_failure(Failure::cast(cell));
763 return result; 990 return reg;
764 } 991 }
765 } 992 }
766 object = JSObject::cast(object->GetPrototype()); 993 current = JSObject::cast(current->GetPrototype());
767 } 994 }
768 995
769 // Return the register containing the holder. 996 // Return the register containing the holder.
770 return result; 997 return reg;
771 } 998 }
772 999
773 1000
774 void StubCompiler::GenerateLoadField(JSObject* object, 1001 void StubCompiler::GenerateLoadField(JSObject* object,
775 JSObject* holder, 1002 JSObject* holder,
776 Register receiver, 1003 Register receiver,
777 Register scratch1, 1004 Register scratch1,
778 Register scratch2, 1005 Register scratch2,
779 int index, 1006 int index,
780 String* name, 1007 String* name,
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after
1046 1273
1047 const int argc = arguments().immediate(); 1274 const int argc = arguments().immediate();
1048 1275
1049 // Get the receiver of the function from the stack into r0. 1276 // Get the receiver of the function from the stack into r0.
1050 __ ldr(r0, MemOperand(sp, argc * kPointerSize)); 1277 __ ldr(r0, MemOperand(sp, argc * kPointerSize));
1051 // Check that the receiver isn't a smi. 1278 // Check that the receiver isn't a smi.
1052 __ tst(r0, Operand(kSmiTagMask)); 1279 __ tst(r0, Operand(kSmiTagMask));
1053 __ b(eq, &miss); 1280 __ b(eq, &miss);
1054 1281
1055 // Do the right check and compute the holder register. 1282 // Do the right check and compute the holder register.
1056 Register reg = CheckPrototypes(object, r0, holder, r1, r3, name, &miss); 1283 Register reg = CheckPrototypes(object, r0, holder, r1, r3, name, &miss, r4);
1057 GenerateFastPropertyLoad(masm(), r1, reg, holder, index); 1284 GenerateFastPropertyLoad(masm(), r1, reg, holder, index);
1058 1285
1059 GenerateCallFunction(masm(), object, arguments(), &miss); 1286 GenerateCallFunction(masm(), object, arguments(), &miss);
1060 1287
1061 // Handle call cache miss. 1288 // Handle call cache miss.
1062 __ bind(&miss); 1289 __ bind(&miss);
1063 GenerateMissBranch(); 1290 GenerateMissBranch();
1064 1291
1065 // Return the generated code. 1292 // Return the generated code.
1066 return GetCode(FIELD, name); 1293 return GetCode(FIELD, name);
(...skipping 24 matching lines...) Expand all
1091 1318
1092 // Get the receiver from the stack 1319 // Get the receiver from the stack
1093 const int argc = arguments().immediate(); 1320 const int argc = arguments().immediate();
1094 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); 1321 __ ldr(r1, MemOperand(sp, argc * kPointerSize));
1095 1322
1096 // Check that the receiver isn't a smi. 1323 // Check that the receiver isn't a smi.
1097 __ tst(r1, Operand(kSmiTagMask)); 1324 __ tst(r1, Operand(kSmiTagMask));
1098 __ b(eq, &miss); 1325 __ b(eq, &miss);
1099 1326
1100 // Check that the maps haven't changed. 1327 // Check that the maps haven't changed.
1101 CheckPrototypes(JSObject::cast(object), r1, holder, r3, r0, name, &miss); 1328 CheckPrototypes(JSObject::cast(object), r1, holder, r3, r0, name, &miss, r4);
1102 1329
1103 if (object->IsGlobalObject()) { 1330 if (object->IsGlobalObject()) {
1104 __ ldr(r3, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); 1331 __ ldr(r3, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset));
1105 __ str(r3, MemOperand(sp, argc * kPointerSize)); 1332 __ str(r3, MemOperand(sp, argc * kPointerSize));
1106 } 1333 }
1107 1334
1108 __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPush), 1335 __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPush),
1109 argc + 1, 1336 argc + 1,
1110 1); 1337 1);
1111 1338
(...skipping 30 matching lines...) Expand all
1142 1369
1143 // Get the receiver from the stack 1370 // Get the receiver from the stack
1144 const int argc = arguments().immediate(); 1371 const int argc = arguments().immediate();
1145 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); 1372 __ ldr(r1, MemOperand(sp, argc * kPointerSize));
1146 1373
1147 // Check that the receiver isn't a smi. 1374 // Check that the receiver isn't a smi.
1148 __ tst(r1, Operand(kSmiTagMask)); 1375 __ tst(r1, Operand(kSmiTagMask));
1149 __ b(eq, &miss); 1376 __ b(eq, &miss);
1150 1377
1151 // Check that the maps haven't changed. 1378 // Check that the maps haven't changed.
1152 CheckPrototypes(JSObject::cast(object), r1, holder, r3, r0, name, &miss); 1379 CheckPrototypes(JSObject::cast(object), r1, holder, r3, r0, name, &miss, r4);
1153 1380
1154 if (object->IsGlobalObject()) { 1381 if (object->IsGlobalObject()) {
1155 __ ldr(r3, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); 1382 __ ldr(r3, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset));
1156 __ str(r3, MemOperand(sp, argc * kPointerSize)); 1383 __ str(r3, MemOperand(sp, argc * kPointerSize));
1157 } 1384 }
1158 1385
1159 __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPop), 1386 __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPop),
1160 argc + 1, 1387 argc + 1,
1161 1); 1388 1);
1162 1389
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
1240 JSObject::cast(object), holder); 1467 JSObject::cast(object), holder);
1241 } 1468 }
1242 1469
1243 if (depth != kInvalidProtoDepth) { 1470 if (depth != kInvalidProtoDepth) {
1244 __ IncrementCounter(&Counters::call_const_fast_api, 1, r0, r3); 1471 __ IncrementCounter(&Counters::call_const_fast_api, 1, r0, r3);
1245 ReserveSpaceForFastApiCall(masm(), r0); 1472 ReserveSpaceForFastApiCall(masm(), r0);
1246 } 1473 }
1247 1474
1248 // Check that the maps haven't changed. 1475 // Check that the maps haven't changed.
1249 CheckPrototypes(JSObject::cast(object), r1, holder, r0, r3, name, 1476 CheckPrototypes(JSObject::cast(object), r1, holder, r0, r3, name,
1250 depth, &miss); 1477 depth, &miss, r4);
1251 1478
1252 // Patch the receiver on the stack with the global proxy if 1479 // Patch the receiver on the stack with the global proxy if
1253 // necessary. 1480 // necessary.
1254 if (object->IsGlobalObject()) { 1481 if (object->IsGlobalObject()) {
1255 ASSERT(depth == kInvalidProtoDepth); 1482 ASSERT(depth == kInvalidProtoDepth);
1256 __ ldr(r3, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); 1483 __ ldr(r3, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset));
1257 __ str(r3, MemOperand(sp, argc * kPointerSize)); 1484 __ str(r3, MemOperand(sp, argc * kPointerSize));
1258 } 1485 }
1259 break; 1486 break;
1260 1487
1261 case STRING_CHECK: 1488 case STRING_CHECK:
1262 if (!function->IsBuiltin()) { 1489 if (!function->IsBuiltin()) {
1263 // Calling non-builtins with a value as receiver requires boxing. 1490 // Calling non-builtins with a value as receiver requires boxing.
1264 __ jmp(&miss); 1491 __ jmp(&miss);
1265 } else { 1492 } else {
1266 // Check that the object is a two-byte string or a symbol. 1493 // Check that the object is a two-byte string or a symbol.
1267 __ CompareObjectType(r1, r3, r3, FIRST_NONSTRING_TYPE); 1494 __ CompareObjectType(r1, r3, r3, FIRST_NONSTRING_TYPE);
1268 __ b(hs, &miss); 1495 __ b(hs, &miss);
1269 // Check that the maps starting from the prototype haven't changed. 1496 // Check that the maps starting from the prototype haven't changed.
1270 GenerateDirectLoadGlobalFunctionPrototype( 1497 GenerateDirectLoadGlobalFunctionPrototype(
1271 masm(), Context::STRING_FUNCTION_INDEX, r0); 1498 masm(), Context::STRING_FUNCTION_INDEX, r0);
1272 CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r3, 1499 CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r3,
1273 r1, name, &miss); 1500 r1, name, &miss, r4);
1274 } 1501 }
1275 break; 1502 break;
1276 1503
1277 case NUMBER_CHECK: { 1504 case NUMBER_CHECK: {
1278 if (!function->IsBuiltin()) { 1505 if (!function->IsBuiltin()) {
1279 // Calling non-builtins with a value as receiver requires boxing. 1506 // Calling non-builtins with a value as receiver requires boxing.
1280 __ jmp(&miss); 1507 __ jmp(&miss);
1281 } else { 1508 } else {
1282 Label fast; 1509 Label fast;
1283 // Check that the object is a smi or a heap number. 1510 // Check that the object is a smi or a heap number.
1284 __ tst(r1, Operand(kSmiTagMask)); 1511 __ tst(r1, Operand(kSmiTagMask));
1285 __ b(eq, &fast); 1512 __ b(eq, &fast);
1286 __ CompareObjectType(r1, r0, r0, HEAP_NUMBER_TYPE); 1513 __ CompareObjectType(r1, r0, r0, HEAP_NUMBER_TYPE);
1287 __ b(ne, &miss); 1514 __ b(ne, &miss);
1288 __ bind(&fast); 1515 __ bind(&fast);
1289 // Check that the maps starting from the prototype haven't changed. 1516 // Check that the maps starting from the prototype haven't changed.
1290 GenerateDirectLoadGlobalFunctionPrototype( 1517 GenerateDirectLoadGlobalFunctionPrototype(
1291 masm(), Context::NUMBER_FUNCTION_INDEX, r0); 1518 masm(), Context::NUMBER_FUNCTION_INDEX, r0);
1292 CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r3, 1519 CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r3,
1293 r1, name, &miss); 1520 r1, name, &miss, r4);
1294 } 1521 }
1295 break; 1522 break;
1296 } 1523 }
1297 1524
1298 case BOOLEAN_CHECK: { 1525 case BOOLEAN_CHECK: {
1299 if (!function->IsBuiltin()) { 1526 if (!function->IsBuiltin()) {
1300 // Calling non-builtins with a value as receiver requires boxing. 1527 // Calling non-builtins with a value as receiver requires boxing.
1301 __ jmp(&miss); 1528 __ jmp(&miss);
1302 } else { 1529 } else {
1303 Label fast; 1530 Label fast;
1304 // Check that the object is a boolean. 1531 // Check that the object is a boolean.
1305 __ LoadRoot(ip, Heap::kTrueValueRootIndex); 1532 __ LoadRoot(ip, Heap::kTrueValueRootIndex);
1306 __ cmp(r1, ip); 1533 __ cmp(r1, ip);
1307 __ b(eq, &fast); 1534 __ b(eq, &fast);
1308 __ LoadRoot(ip, Heap::kFalseValueRootIndex); 1535 __ LoadRoot(ip, Heap::kFalseValueRootIndex);
1309 __ cmp(r1, ip); 1536 __ cmp(r1, ip);
1310 __ b(ne, &miss); 1537 __ b(ne, &miss);
1311 __ bind(&fast); 1538 __ bind(&fast);
1312 // Check that the maps starting from the prototype haven't changed. 1539 // Check that the maps starting from the prototype haven't changed.
1313 GenerateDirectLoadGlobalFunctionPrototype( 1540 GenerateDirectLoadGlobalFunctionPrototype(
1314 masm(), Context::BOOLEAN_FUNCTION_INDEX, r0); 1541 masm(), Context::BOOLEAN_FUNCTION_INDEX, r0);
1315 CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r3, 1542 CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r3,
1316 r1, name, &miss); 1543 r1, name, &miss, r4);
1317 } 1544 }
1318 break; 1545 break;
1319 } 1546 }
1320 1547
1321 default: 1548 default:
1322 UNREACHABLE(); 1549 UNREACHABLE();
1323 } 1550 }
1324 1551
1325 if (depth != kInvalidProtoDepth) { 1552 if (depth != kInvalidProtoDepth) {
1326 GenerateFastApiCall(masm(), optimization, argc); 1553 GenerateFastApiCall(masm(), optimization, argc);
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
1411 1638
1412 // If the object is the holder then we know that it's a global 1639 // If the object is the holder then we know that it's a global
1413 // object which can only happen for contextual calls. In this case, 1640 // object which can only happen for contextual calls. In this case,
1414 // the receiver cannot be a smi. 1641 // the receiver cannot be a smi.
1415 if (object != holder) { 1642 if (object != holder) {
1416 __ tst(r0, Operand(kSmiTagMask)); 1643 __ tst(r0, Operand(kSmiTagMask));
1417 __ b(eq, &miss); 1644 __ b(eq, &miss);
1418 } 1645 }
1419 1646
1420 // Check that the maps haven't changed. 1647 // Check that the maps haven't changed.
1421 CheckPrototypes(object, r0, holder, r3, r1, name, &miss); 1648 CheckPrototypes(object, r0, holder, r3, r1, name, &miss, r4);
1422 1649
1423 // Get the value from the cell. 1650 // Get the value from the cell.
1424 __ mov(r3, Operand(Handle<JSGlobalPropertyCell>(cell))); 1651 __ mov(r3, Operand(Handle<JSGlobalPropertyCell>(cell)));
1425 __ ldr(r1, FieldMemOperand(r3, JSGlobalPropertyCell::kValueOffset)); 1652 __ ldr(r1, FieldMemOperand(r3, JSGlobalPropertyCell::kValueOffset));
1426 1653
1427 // Check that the cell contains the same function. 1654 // Check that the cell contains the same function.
1428 if (Heap::InNewSpace(function)) { 1655 if (Heap::InNewSpace(function)) {
1429 // We can't embed a pointer to a function in new space so we have 1656 // We can't embed a pointer to a function in new space so we have
1430 // to verify that the shared function info is unchanged. This has 1657 // to verify that the shared function info is unchanged. This has
1431 // the nice side effect that multiple closures based on the same 1658 // the nice side effect that multiple closures based on the same
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after
1635 // -- r0 : receiver 1862 // -- r0 : receiver
1636 // -- lr : return address 1863 // -- lr : return address
1637 // ----------------------------------- 1864 // -----------------------------------
1638 Label miss; 1865 Label miss;
1639 1866
1640 // Check that receiver is not a smi. 1867 // Check that receiver is not a smi.
1641 __ tst(r0, Operand(kSmiTagMask)); 1868 __ tst(r0, Operand(kSmiTagMask));
1642 __ b(eq, &miss); 1869 __ b(eq, &miss);
1643 1870
1644 // Check the maps of the full prototype chain. 1871 // Check the maps of the full prototype chain.
1645 CheckPrototypes(object, r0, last, r3, r1, name, &miss); 1872 CheckPrototypes(object, r0, last, r3, r1, name, &miss, r4);
1646 1873
1647 // If the last object in the prototype chain is a global object, 1874 // If the last object in the prototype chain is a global object,
1648 // check that the global property cell is empty. 1875 // check that the global property cell is empty.
1649 if (last->IsGlobalObject()) { 1876 if (last->IsGlobalObject()) {
1650 Object* cell = GenerateCheckPropertyCell(masm(), 1877 Object* cell = GenerateCheckPropertyCell(masm(),
1651 GlobalObject::cast(last), 1878 GlobalObject::cast(last),
1652 name, 1879 name,
1653 r1, 1880 r1,
1654 &miss); 1881 &miss);
1655 if (cell->IsFailure()) return cell; 1882 if (cell->IsFailure()) return cell;
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
1775 2002
1776 // If the object is the holder then we know that it's a global 2003 // If the object is the holder then we know that it's a global
1777 // object which can only happen for contextual calls. In this case, 2004 // object which can only happen for contextual calls. In this case,
1778 // the receiver cannot be a smi. 2005 // the receiver cannot be a smi.
1779 if (object != holder) { 2006 if (object != holder) {
1780 __ tst(r0, Operand(kSmiTagMask)); 2007 __ tst(r0, Operand(kSmiTagMask));
1781 __ b(eq, &miss); 2008 __ b(eq, &miss);
1782 } 2009 }
1783 2010
1784 // Check that the map of the global has not changed. 2011 // Check that the map of the global has not changed.
1785 CheckPrototypes(object, r0, holder, r3, r4, name, &miss); 2012 CheckPrototypes(object, r0, holder, r3, r4, name, &miss, r1);
1786 2013
1787 // Get the value from the cell. 2014 // Get the value from the cell.
1788 __ mov(r3, Operand(Handle<JSGlobalPropertyCell>(cell))); 2015 __ mov(r3, Operand(Handle<JSGlobalPropertyCell>(cell)));
1789 __ ldr(r4, FieldMemOperand(r3, JSGlobalPropertyCell::kValueOffset)); 2016 __ ldr(r4, FieldMemOperand(r3, JSGlobalPropertyCell::kValueOffset));
1790 2017
1791 // Check for deleted property if property can actually be deleted. 2018 // Check for deleted property if property can actually be deleted.
1792 if (!is_dont_delete) { 2019 if (!is_dont_delete) {
1793 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 2020 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
1794 __ cmp(r4, ip); 2021 __ cmp(r4, ip);
1795 __ b(eq, &miss); 2022 __ b(eq, &miss);
(...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after
2149 // Return the generated code. 2376 // Return the generated code.
2150 return GetCode(); 2377 return GetCode();
2151 } 2378 }
2152 2379
2153 2380
2154 #undef __ 2381 #undef __
2155 2382
2156 } } // namespace v8::internal 2383 } } // namespace v8::internal
2157 2384
2158 #endif // V8_TARGET_ARCH_ARM 2385 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « src/arm/macro-assembler-arm.cc ('k') | src/ia32/stub-cache-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698