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

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

Issue 12209021: Refactor LoadIC into Handler Frontend and Backends. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Load from correct reg on ARM. Created 7 years, 10 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 | « no previous file | 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 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 1150 matching lines...) Expand 10 before | Expand all | Expand 10 after
1161 // If we've skipped any global objects, it's not enough to verify that 1161 // If we've skipped any global objects, it's not enough to verify that
1162 // their maps haven't changed. We also need to check that the property 1162 // their maps haven't changed. We also need to check that the property
1163 // cell for the property is still empty. 1163 // cell for the property is still empty.
1164 GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss); 1164 GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss);
1165 1165
1166 // Return the register containing the holder. 1166 // Return the register containing the holder.
1167 return reg; 1167 return reg;
1168 } 1168 }
1169 1169
1170 1170
1171 void StubCompiler::GenerateLoadField(Handle<JSObject> object, 1171 void BaseLoadStubCompiler::HandlerFrontendFooter(Label* success,
1172 Handle<JSObject> holder, 1172 Label* miss) {
1173 Register receiver, 1173 __ b(success);
1174 Register scratch1, 1174 __ bind(miss);
1175 Register scratch2, 1175 GenerateLoadMiss(masm(), kind());
1176 Register scratch3, 1176 }
1177 PropertyIndex index,
1178 Handle<String> name,
1179 Label* miss) {
1180 // Check that the receiver isn't a smi.
1181 __ JumpIfSmi(receiver, miss);
1182 1177
1183 // Check that the maps haven't changed. 1178
1184 Register reg = CheckPrototypes( 1179 Register BaseLoadStubCompiler::CallbackHandlerFrontend(
1185 object, receiver, holder, scratch1, scratch2, scratch3, name, miss); 1180 Handle<JSObject> object,
1181 Register object_reg,
1182 Handle<JSObject> holder,
1183 Handle<String> name,
1184 Label* success,
1185 FrontendCheckType check,
1186 Handle<AccessorInfo> callback) {
1187 Label miss;
1188
1189 Register reg = HandlerFrontendHeader(
1190 object, object_reg, holder, name, &miss, check);
1191
1192 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) {
1193 ASSERT(!reg.is(scratch2()));
1194 ASSERT(!reg.is(scratch3()));
1195 ASSERT(!reg.is(scratch4()));
1196
1197 // Load the properties dictionary.
1198 Register dictionary = scratch4();
1199 __ ldr(dictionary, FieldMemOperand(reg, JSObject::kPropertiesOffset));
1200
1201 // Probe the dictionary.
1202 Label probe_done;
1203 StringDictionaryLookupStub::GeneratePositiveLookup(masm(),
1204 &miss,
1205 &probe_done,
1206 dictionary,
1207 this->name(),
1208 scratch2(),
1209 scratch3());
1210 __ bind(&probe_done);
1211
1212 // If probing finds an entry in the dictionary, scratch3 contains the
1213 // pointer into the dictionary. Check that the value is the callback.
1214 Register pointer = scratch3();
1215 const int kElementsStartOffset = StringDictionary::kHeaderSize +
1216 StringDictionary::kElementsStartIndex * kPointerSize;
1217 const int kValueOffset = kElementsStartOffset + kPointerSize;
1218 __ ldr(scratch2(), FieldMemOperand(pointer, kValueOffset));
1219 __ cmp(scratch2(), Operand(callback));
1220 __ b(ne, &miss);
1221 }
1222
1223 HandlerFrontendFooter(success, &miss);
1224 return reg;
1225 }
1226
1227
1228 void BaseLoadStubCompiler::NonexistentHandlerFrontend(
1229 Handle<JSObject> object,
1230 Handle<JSObject> last,
1231 Handle<String> name,
1232 Label* success,
1233 Handle<GlobalObject> global) {
1234 Label miss;
1235
1236 Register reg = HandlerFrontendHeader(
1237 object, receiver(), last, name, &miss, PERFORM_INITIAL_CHECKS);
1238
1239 // If the last object in the prototype chain is a global object,
1240 // check that the global property cell is empty.
1241 if (!global.is_null()) {
1242 GenerateCheckPropertyCell(masm(), global, name, scratch2(), &miss);
1243 }
1244
1245 if (!last->HasFastProperties()) {
1246 __ ldr(scratch2(), FieldMemOperand(reg, HeapObject::kMapOffset));
1247 __ ldr(scratch2(), FieldMemOperand(scratch2(), Map::kPrototypeOffset));
1248 __ cmp(scratch2(), Operand(isolate()->factory()->null_value()));
1249 __ b(ne, &miss);
1250 }
1251
1252 HandlerFrontendFooter(success, &miss);
1253 }
1254
1255
1256 void BaseLoadStubCompiler::GenerateLoadField(Register reg,
1257 Handle<JSObject> holder,
1258 PropertyIndex index) {
1186 GenerateFastPropertyLoad(masm(), r0, reg, holder, index); 1259 GenerateFastPropertyLoad(masm(), r0, reg, holder, index);
1187 __ Ret(); 1260 __ Ret();
1188 } 1261 }
1189 1262
1190 1263
1191 void StubCompiler::GenerateLoadConstant(Handle<JSObject> object, 1264 void BaseLoadStubCompiler::GenerateLoadConstant(Handle<JSFunction> value) {
1192 Handle<JSObject> holder,
1193 Register receiver,
1194 Register scratch1,
1195 Register scratch2,
1196 Register scratch3,
1197 Handle<JSFunction> value,
1198 Handle<String> name,
1199 Label* miss) {
1200 // Check that the receiver isn't a smi.
1201 __ JumpIfSmi(receiver, miss);
1202
1203 // Check that the maps haven't changed.
1204 CheckPrototypes(
1205 object, receiver, holder, scratch1, scratch2, scratch3, name, miss);
1206
1207 // Return the constant value. 1265 // Return the constant value.
1208 __ LoadHeapObject(r0, value); 1266 __ LoadHeapObject(r0, value);
1209 __ Ret(); 1267 __ Ret();
1210 } 1268 }
1211 1269
1212 1270
1213 void StubCompiler::GenerateDictionaryLoadCallback(Register receiver, 1271 void BaseLoadStubCompiler::GenerateLoadCallback(Register reg,
1214 Register name_reg, 1272 Handle<AccessorInfo> callback) {
1215 Register scratch1,
1216 Register scratch2,
1217 Register scratch3,
1218 Handle<AccessorInfo> callback,
1219 Handle<String> name,
1220 Label* miss) {
1221 ASSERT(!receiver.is(scratch1));
1222 ASSERT(!receiver.is(scratch2));
1223 ASSERT(!receiver.is(scratch3));
1224
1225 // Load the properties dictionary.
1226 Register dictionary = scratch1;
1227 __ ldr(dictionary, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
1228
1229 // Probe the dictionary.
1230 Label probe_done;
1231 StringDictionaryLookupStub::GeneratePositiveLookup(masm(),
1232 miss,
1233 &probe_done,
1234 dictionary,
1235 name_reg,
1236 scratch2,
1237 scratch3);
1238 __ bind(&probe_done);
1239
1240 // If probing finds an entry in the dictionary, scratch3 contains the
1241 // pointer into the dictionary. Check that the value is the callback.
1242 Register pointer = scratch3;
1243 const int kElementsStartOffset = StringDictionary::kHeaderSize +
1244 StringDictionary::kElementsStartIndex * kPointerSize;
1245 const int kValueOffset = kElementsStartOffset + kPointerSize;
1246 __ ldr(scratch2, FieldMemOperand(pointer, kValueOffset));
1247 __ cmp(scratch2, Operand(callback));
1248 __ b(ne, miss);
1249 }
1250
1251
1252 void StubCompiler::GenerateLoadCallback(Handle<JSObject> object,
1253 Handle<JSObject> holder,
1254 Register receiver,
1255 Register name_reg,
1256 Register scratch1,
1257 Register scratch2,
1258 Register scratch3,
1259 Register scratch4,
1260 Handle<AccessorInfo> callback,
1261 Handle<String> name,
1262 Label* miss) {
1263 // Check that the receiver isn't a smi.
1264 __ JumpIfSmi(receiver, miss);
1265
1266 // Check that the maps haven't changed.
1267 Register reg = CheckPrototypes(object, receiver, holder, scratch1,
1268 scratch2, scratch3, name, miss);
1269
1270 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) {
1271 GenerateDictionaryLoadCallback(
1272 reg, name_reg, scratch2, scratch3, scratch4, callback, name, miss);
1273 }
1274
1275 // Build AccessorInfo::args_ list on the stack and push property name below 1273 // Build AccessorInfo::args_ list on the stack and push property name below
1276 // the exit frame to make GC aware of them and store pointers to them. 1274 // the exit frame to make GC aware of them and store pointers to them.
1277 __ push(receiver); 1275 __ push(receiver());
1278 __ mov(scratch2, sp); // scratch2 = AccessorInfo::args_ 1276 __ mov(scratch2(), sp); // scratch2 = AccessorInfo::args_
1279 if (heap()->InNewSpace(callback->data())) { 1277 if (heap()->InNewSpace(callback->data())) {
1280 __ Move(scratch3, callback); 1278 __ Move(scratch3(), callback);
1281 __ ldr(scratch3, FieldMemOperand(scratch3, AccessorInfo::kDataOffset)); 1279 __ ldr(scratch3(), FieldMemOperand(scratch3(), AccessorInfo::kDataOffset));
1282 } else { 1280 } else {
1283 __ Move(scratch3, Handle<Object>(callback->data())); 1281 __ Move(scratch3(), Handle<Object>(callback->data()));
1284 } 1282 }
1285 __ Push(reg, scratch3); 1283 __ Push(reg, scratch3());
1286 __ mov(scratch3, Operand(ExternalReference::isolate_address())); 1284 __ mov(scratch3(), Operand(ExternalReference::isolate_address()));
1287 __ Push(scratch3, name_reg); 1285 __ Push(scratch3(), name());
1288 __ mov(r0, sp); // r0 = Handle<String> 1286 __ mov(r0, sp); // r0 = Handle<String>
1289 1287
1290 const int kApiStackSpace = 1; 1288 const int kApiStackSpace = 1;
1291 FrameScope frame_scope(masm(), StackFrame::MANUAL); 1289 FrameScope frame_scope(masm(), StackFrame::MANUAL);
1292 __ EnterExitFrame(false, kApiStackSpace); 1290 __ EnterExitFrame(false, kApiStackSpace);
1293 1291
1294 // Create AccessorInfo instance on the stack above the exit frame with 1292 // Create AccessorInfo instance on the stack above the exit frame with
1295 // scratch2 (internal::Object** args_) as the data. 1293 // scratch2 (internal::Object** args_) as the data.
1296 __ str(scratch2, MemOperand(sp, 1 * kPointerSize)); 1294 __ str(scratch2(), MemOperand(sp, 1 * kPointerSize));
1297 __ add(r1, sp, Operand(1 * kPointerSize)); // r1 = AccessorInfo& 1295 __ add(r1, sp, Operand(1 * kPointerSize)); // r1 = AccessorInfo&
1298 1296
1299 const int kStackUnwindSpace = 5; 1297 const int kStackUnwindSpace = 5;
1300 Address getter_address = v8::ToCData<Address>(callback->getter()); 1298 Address getter_address = v8::ToCData<Address>(callback->getter());
1301 ApiFunction fun(getter_address); 1299 ApiFunction fun(getter_address);
1302 ExternalReference ref = 1300 ExternalReference ref =
1303 ExternalReference(&fun, 1301 ExternalReference(&fun,
1304 ExternalReference::DIRECT_GETTER_CALL, 1302 ExternalReference::DIRECT_GETTER_CALL,
1305 masm()->isolate()); 1303 masm()->isolate());
1306 __ CallApiFunctionAndReturn(ref, kStackUnwindSpace); 1304 __ CallApiFunctionAndReturn(ref, kStackUnwindSpace);
1307 } 1305 }
1308 1306
1309 1307
1310 void StubCompiler::GenerateLoadInterceptor(Handle<JSObject> object, 1308 void BaseLoadStubCompiler::GenerateLoadInterceptor(
1311 Handle<JSObject> interceptor_holder, 1309 Register holder_reg,
1312 LookupResult* lookup, 1310 Handle<JSObject> object,
1313 Register receiver, 1311 Handle<JSObject> interceptor_holder,
1314 Register name_reg, 1312 LookupResult* lookup,
1315 Register scratch1, 1313 Handle<String> name) {
1316 Register scratch2,
1317 Register scratch3,
1318 Handle<String> name,
1319 Label* miss) {
1320 ASSERT(interceptor_holder->HasNamedInterceptor()); 1314 ASSERT(interceptor_holder->HasNamedInterceptor());
1321 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); 1315 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined());
1322 1316
1323 // Check that the receiver isn't a smi.
1324 __ JumpIfSmi(receiver, miss);
1325
1326 // So far the most popular follow ups for interceptor loads are FIELD 1317 // So far the most popular follow ups for interceptor loads are FIELD
1327 // and CALLBACKS, so inline only them, other cases may be added 1318 // and CALLBACKS, so inline only them, other cases may be added
1328 // later. 1319 // later.
1329 bool compile_followup_inline = false; 1320 bool compile_followup_inline = false;
1330 if (lookup->IsFound() && lookup->IsCacheable()) { 1321 if (lookup->IsFound() && lookup->IsCacheable()) {
1331 if (lookup->IsField()) { 1322 if (lookup->IsField()) {
1332 compile_followup_inline = true; 1323 compile_followup_inline = true;
1333 } else if (lookup->type() == CALLBACKS && 1324 } else if (lookup->type() == CALLBACKS &&
1334 lookup->GetCallbackObject()->IsAccessorInfo()) { 1325 lookup->GetCallbackObject()->IsAccessorInfo()) {
1335 AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject()); 1326 AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject());
1336 compile_followup_inline = callback->getter() != NULL && 1327 compile_followup_inline = callback->getter() != NULL &&
1337 callback->IsCompatibleReceiver(*object); 1328 callback->IsCompatibleReceiver(*object);
1338 } 1329 }
1339 } 1330 }
1340 1331
1341 if (compile_followup_inline) { 1332 if (compile_followup_inline) {
1342 // Compile the interceptor call, followed by inline code to load the 1333 // Compile the interceptor call, followed by inline code to load the
1343 // property from further up the prototype chain if the call fails. 1334 // property from further up the prototype chain if the call fails.
1344 // Check that the maps haven't changed. 1335 // Check that the maps haven't changed.
1345 Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder, 1336 ASSERT(holder_reg.is(receiver()) || holder_reg.is(scratch1()));
1346 scratch1, scratch2, scratch3,
1347 name, miss);
1348 ASSERT(holder_reg.is(receiver) || holder_reg.is(scratch1));
1349 1337
1350 // Preserve the receiver register explicitly whenever it is different from 1338 // Preserve the receiver register explicitly whenever it is different from
1351 // the holder and it is needed should the interceptor return without any 1339 // the holder and it is needed should the interceptor return without any
1352 // result. The CALLBACKS case needs the receiver to be passed into C++ code, 1340 // result. The CALLBACKS case needs the receiver to be passed into C++ code,
1353 // the FIELD case might cause a miss during the prototype check. 1341 // the FIELD case might cause a miss during the prototype check.
1354 bool must_perfrom_prototype_check = *interceptor_holder != lookup->holder(); 1342 bool must_perfrom_prototype_check = *interceptor_holder != lookup->holder();
1355 bool must_preserve_receiver_reg = !receiver.is(holder_reg) && 1343 bool must_preserve_receiver_reg = !receiver().is(holder_reg) &&
1356 (lookup->type() == CALLBACKS || must_perfrom_prototype_check); 1344 (lookup->type() == CALLBACKS || must_perfrom_prototype_check);
1357 1345
1358 // Save necessary data before invoking an interceptor. 1346 // Save necessary data before invoking an interceptor.
1359 // Requires a frame to make GC aware of pushed pointers. 1347 // Requires a frame to make GC aware of pushed pointers.
1360 { 1348 {
1361 FrameScope frame_scope(masm(), StackFrame::INTERNAL); 1349 FrameScope frame_scope(masm(), StackFrame::INTERNAL);
1362 if (must_preserve_receiver_reg) { 1350 if (must_preserve_receiver_reg) {
1363 __ Push(receiver, holder_reg, name_reg); 1351 __ Push(receiver(), holder_reg, this->name());
1364 } else { 1352 } else {
1365 __ Push(holder_reg, name_reg); 1353 __ Push(holder_reg, this->name());
1366 } 1354 }
1367 // Invoke an interceptor. Note: map checks from receiver to 1355 // Invoke an interceptor. Note: map checks from receiver to
1368 // interceptor's holder has been compiled before (see a caller 1356 // interceptor's holder has been compiled before (see a caller
1369 // of this method.) 1357 // of this method.)
1370 CompileCallLoadPropertyWithInterceptor(masm(), 1358 CompileCallLoadPropertyWithInterceptor(masm(),
1371 receiver, 1359 receiver(),
1372 holder_reg, 1360 holder_reg,
1373 name_reg, 1361 this->name(),
1374 interceptor_holder); 1362 interceptor_holder);
1375 // Check if interceptor provided a value for property. If it's 1363 // Check if interceptor provided a value for property. If it's
1376 // the case, return immediately. 1364 // the case, return immediately.
1377 Label interceptor_failed; 1365 Label interceptor_failed;
1378 __ LoadRoot(scratch1, Heap::kNoInterceptorResultSentinelRootIndex); 1366 __ LoadRoot(scratch1(), Heap::kNoInterceptorResultSentinelRootIndex);
1379 __ cmp(r0, scratch1); 1367 __ cmp(r0, scratch1());
1380 __ b(eq, &interceptor_failed); 1368 __ b(eq, &interceptor_failed);
1381 frame_scope.GenerateLeaveFrame(); 1369 frame_scope.GenerateLeaveFrame();
1382 __ Ret(); 1370 __ Ret();
1383 1371
1384 __ bind(&interceptor_failed); 1372 __ bind(&interceptor_failed);
1385 __ pop(name_reg); 1373 __ pop(this->name());
1386 __ pop(holder_reg); 1374 __ pop(holder_reg);
1387 if (must_preserve_receiver_reg) { 1375 if (must_preserve_receiver_reg) {
1388 __ pop(receiver); 1376 __ pop(receiver());
1389 } 1377 }
1390 // Leave the internal frame. 1378 // Leave the internal frame.
1391 } 1379 }
1392 // Check that the maps from interceptor's holder to lookup's holder
1393 // haven't changed. And load lookup's holder into |holder| register.
1394 if (must_perfrom_prototype_check) {
1395 holder_reg = CheckPrototypes(interceptor_holder,
1396 holder_reg,
1397 Handle<JSObject>(lookup->holder()),
1398 scratch1,
1399 scratch2,
1400 scratch3,
1401 name,
1402 miss);
1403 }
1404 1380
1405 if (lookup->IsField()) { 1381 GenerateLoadPostInterceptor(holder_reg, interceptor_holder, name, lookup);
1406 // We found FIELD property in prototype chain of interceptor's holder.
1407 // Retrieve a field from field's holder.
1408 GenerateFastPropertyLoad(masm(), r0, holder_reg,
1409 Handle<JSObject>(lookup->holder()),
1410 lookup->GetFieldIndex());
1411 __ Ret();
1412 } else {
1413 // We found CALLBACKS property in prototype chain of interceptor's
1414 // holder.
1415 ASSERT(lookup->type() == CALLBACKS);
1416 Handle<AccessorInfo> callback(
1417 AccessorInfo::cast(lookup->GetCallbackObject()));
1418 ASSERT(callback->getter() != NULL);
1419
1420 // Tail call to runtime.
1421 // Important invariant in CALLBACKS case: the code above must be
1422 // structured to never clobber |receiver| register.
1423 __ Move(scratch2, callback);
1424 // holder_reg is either receiver or scratch1.
1425 if (!receiver.is(holder_reg)) {
1426 ASSERT(scratch1.is(holder_reg));
1427 __ Push(receiver, holder_reg);
1428 } else {
1429 __ push(receiver);
1430 __ push(holder_reg);
1431 }
1432 __ ldr(scratch3,
1433 FieldMemOperand(scratch2, AccessorInfo::kDataOffset));
1434 __ mov(scratch1, Operand(ExternalReference::isolate_address()));
1435 __ Push(scratch3, scratch1, scratch2, name_reg);
1436
1437 ExternalReference ref =
1438 ExternalReference(IC_Utility(IC::kLoadCallbackProperty),
1439 masm()->isolate());
1440 __ TailCallExternalReference(ref, 6, 1);
1441 }
1442 } else { // !compile_followup_inline 1382 } else { // !compile_followup_inline
1443 // Call the runtime system to load the interceptor. 1383 // Call the runtime system to load the interceptor.
1444 // Check that the maps haven't changed. 1384 // Check that the maps haven't changed.
1445 Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder, 1385 PushInterceptorArguments(masm(), receiver(), holder_reg,
1446 scratch1, scratch2, scratch3, 1386 this->name(), interceptor_holder);
1447 name, miss);
1448 PushInterceptorArguments(masm(), receiver, holder_reg,
1449 name_reg, interceptor_holder);
1450 1387
1451 ExternalReference ref = 1388 ExternalReference ref =
1452 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), 1389 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForLoad),
1453 masm()->isolate()); 1390 masm()->isolate());
1454 __ TailCallExternalReference(ref, 6, 1); 1391 __ TailCallExternalReference(ref, 6, 1);
1455 } 1392 }
1456 } 1393 }
1457 1394
1458 1395
1459 void CallStubCompiler::GenerateNameCheck(Handle<String> name, Label* miss) { 1396 void CallStubCompiler::GenerateNameCheck(Handle<String> name, Label* miss) {
(...skipping 1435 matching lines...) Expand 10 before | Expand all | Expand 10 after
2895 // Return the generated code. 2832 // Return the generated code.
2896 return GetCode(Code::NORMAL, name); 2833 return GetCode(Code::NORMAL, name);
2897 } 2834 }
2898 2835
2899 2836
2900 Handle<Code> LoadStubCompiler::CompileLoadNonexistent( 2837 Handle<Code> LoadStubCompiler::CompileLoadNonexistent(
2901 Handle<JSObject> object, 2838 Handle<JSObject> object,
2902 Handle<JSObject> last, 2839 Handle<JSObject> last,
2903 Handle<String> name, 2840 Handle<String> name,
2904 Handle<GlobalObject> global) { 2841 Handle<GlobalObject> global) {
2905 // ----------- S t a t e ------------- 2842 Label success;
2906 // -- r0 : receiver
2907 // -- lr : return address
2908 // -----------------------------------
2909 Label miss;
2910 2843
2911 // Check that receiver is not a smi. 2844 NonexistentHandlerFrontend(object, last, name, &success, global);
2912 __ JumpIfSmi(r0, &miss);
2913 2845
2914 2846 __ bind(&success);
2915 Register scratch = r1;
2916
2917 // Check the maps of the full prototype chain.
2918 Register result =
2919 CheckPrototypes(object, r0, last, r3, scratch, r4, name, &miss);
2920
2921 // If the last object in the prototype chain is a global object,
2922 // check that the global property cell is empty.
2923 if (!global.is_null()) {
2924 GenerateCheckPropertyCell(masm(), global, name, scratch, &miss);
2925 }
2926
2927 if (!last->HasFastProperties()) {
2928 __ ldr(scratch, FieldMemOperand(result, HeapObject::kMapOffset));
2929 __ ldr(scratch, FieldMemOperand(scratch, Map::kPrototypeOffset));
2930 __ cmp(scratch, Operand(isolate()->factory()->null_value()));
2931 __ b(ne, &miss);
2932 }
2933
2934 // Return undefined if maps of the full prototype chain are still the 2847 // Return undefined if maps of the full prototype chain are still the
2935 // same and no global property with this name contains a value. 2848 // same and no global property with this name contains a value.
2936 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); 2849 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
2937 __ Ret(); 2850 __ Ret();
2938 2851
2939 __ bind(&miss);
2940 GenerateLoadMiss(masm(), Code::LOAD_IC);
2941
2942 // Return the generated code. 2852 // Return the generated code.
2943 return GetCode(Code::NONEXISTENT, factory()->empty_string()); 2853 return GetCode(Code::NONEXISTENT, factory()->empty_string());
2944 } 2854 }
2945 2855
2946 2856
2947 Register* LoadStubCompiler::registers() { 2857 Register* LoadStubCompiler::registers() {
2948 // receiver, name, scratch1, scratch2, scratch3, scratch4. 2858 // receiver, name, scratch1, scratch2, scratch3, scratch4.
2949 static Register registers[] = { r0, r2, r3, r1, r4, r5 }; 2859 static Register registers[] = { r0, r2, r3, r1, r4, r5 };
2950 return registers; 2860 return registers;
2951 } 2861 }
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
2996 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 2906 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
2997 } 2907 }
2998 __ Ret(); 2908 __ Ret();
2999 } 2909 }
3000 2910
3001 2911
3002 #undef __ 2912 #undef __
3003 #define __ ACCESS_MASM(masm()) 2913 #define __ ACCESS_MASM(masm())
3004 2914
3005 2915
3006 Handle<Code> LoadStubCompiler::CompileLoadViaGetter(
3007 Handle<JSObject> receiver,
3008 Handle<JSObject> holder,
3009 Handle<String> name,
3010 Handle<JSFunction> getter) {
3011 // ----------- S t a t e -------------
3012 // -- r0 : receiver
3013 // -- r2 : name
3014 // -- lr : return address
3015 // -----------------------------------
3016 Label miss;
3017
3018 // Check that the maps haven't changed.
3019 __ JumpIfSmi(r0, &miss);
3020 CheckPrototypes(receiver, r0, holder, r3, r4, r1, name, &miss);
3021
3022 GenerateLoadViaGetter(masm(), getter);
3023
3024 __ bind(&miss);
3025 GenerateLoadMiss(masm(), Code::LOAD_IC);
3026
3027 // Return the generated code.
3028 return GetCode(Code::CALLBACKS, name);
3029 }
3030
3031
3032 Handle<Code> LoadStubCompiler::CompileLoadGlobal( 2916 Handle<Code> LoadStubCompiler::CompileLoadGlobal(
3033 Handle<JSObject> object, 2917 Handle<JSObject> object,
3034 Handle<GlobalObject> holder, 2918 Handle<GlobalObject> global,
3035 Handle<JSGlobalPropertyCell> cell, 2919 Handle<JSGlobalPropertyCell> cell,
3036 Handle<String> name, 2920 Handle<String> name,
3037 bool is_dont_delete) { 2921 bool is_dont_delete) {
3038 // ----------- S t a t e ------------- 2922 Label success, miss;
3039 // -- r0 : receiver
3040 // -- r2 : name
3041 // -- lr : return address
3042 // -----------------------------------
3043 Label miss;
3044 2923
3045 // Check that the map of the global has not changed. 2924 HandlerFrontendHeader(object, receiver(), Handle<JSObject>::cast(global),
3046 __ JumpIfSmi(r0, &miss); 2925 name, &miss, PERFORM_INITIAL_CHECKS);
3047 CheckPrototypes(object, r0, holder, r3, r4, r1, name, &miss);
3048 2926
3049 // Get the value from the cell. 2927 // Get the value from the cell.
3050 __ mov(r3, Operand(cell)); 2928 __ mov(r3, Operand(cell));
3051 __ ldr(r4, FieldMemOperand(r3, JSGlobalPropertyCell::kValueOffset)); 2929 __ ldr(r4, FieldMemOperand(r3, JSGlobalPropertyCell::kValueOffset));
3052 2930
3053 // Check for deleted property if property can actually be deleted. 2931 // Check for deleted property if property can actually be deleted.
3054 if (!is_dont_delete) { 2932 if (!is_dont_delete) {
3055 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 2933 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
3056 __ cmp(r4, ip); 2934 __ cmp(r4, ip);
3057 __ b(eq, &miss); 2935 __ b(eq, &miss);
3058 } 2936 }
3059 2937
3060 __ mov(r0, r4); 2938 HandlerFrontendFooter(&success, &miss);
2939 __ bind(&success);
2940
3061 Counters* counters = masm()->isolate()->counters(); 2941 Counters* counters = masm()->isolate()->counters();
3062 __ IncrementCounter(counters->named_load_global_stub(), 1, r1, r3); 2942 __ IncrementCounter(counters->named_load_global_stub(), 1, r1, r3);
2943 __ mov(r0, r4);
3063 __ Ret(); 2944 __ Ret();
3064 2945
3065 __ bind(&miss);
3066 __ IncrementCounter(counters->named_load_global_stub_miss(), 1, r1, r3);
3067 GenerateLoadMiss(masm(), Code::LOAD_IC);
3068
3069 // Return the generated code. 2946 // Return the generated code.
3070 return GetCode(Code::NORMAL, name); 2947 return GetCode(Code::NORMAL, name);
3071 } 2948 }
3072 2949
3073 2950
3074 Handle<Code> KeyedLoadStubCompiler::CompileLoadElement( 2951 Handle<Code> KeyedLoadStubCompiler::CompileLoadElement(
3075 Handle<Map> receiver_map) { 2952 Handle<Map> receiver_map) {
3076 // ----------- S t a t e ------------- 2953 // ----------- S t a t e -------------
3077 // -- lr : return address 2954 // -- lr : return address
3078 // -- r0 : key 2955 // -- r0 : key
(...skipping 1089 matching lines...) Expand 10 before | Expand all | Expand 10 after
4168 __ Jump(ic_slow, RelocInfo::CODE_TARGET); 4045 __ Jump(ic_slow, RelocInfo::CODE_TARGET);
4169 } 4046 }
4170 } 4047 }
4171 4048
4172 4049
4173 #undef __ 4050 #undef __
4174 4051
4175 } } // namespace v8::internal 4052 } } // namespace v8::internal
4176 4053
4177 #endif // V8_TARGET_ARCH_ARM 4054 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « no previous file | src/ia32/stub-cache-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698