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

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

Issue 12378061: MIPS: Currently this mostly just moves code around. (Closed) Base URL: https://v8.googlecode.com/svn/branches/3.16
Patch Set: Created 7 years, 9 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 | no next file » | 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 __ Branch(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<ExecutableAccessorInfo> 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 __ lw(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 __ lw(scratch2(), FieldMemOperand(pointer, kValueOffset));
1219 __ Branch(&miss, ne, scratch2(), Operand(callback));
1220 }
1221
1222 HandlerFrontendFooter(success, &miss);
1223 return reg;
1224 }
1225
1226
1227 void BaseLoadStubCompiler::NonexistentHandlerFrontend(
1228 Handle<JSObject> object,
1229 Handle<JSObject> last,
1230 Handle<String> name,
1231 Label* success,
1232 Handle<GlobalObject> global) {
1233 Label miss;
1234
1235 Register reg = HandlerFrontendHeader(
1236 object, receiver(), last, name, &miss, PERFORM_INITIAL_CHECKS);
1237
1238 // If the last object in the prototype chain is a global object,
1239 // check that the global property cell is empty.
1240 if (!global.is_null()) {
1241 GenerateCheckPropertyCell(masm(), global, name, scratch2(), &miss);
1242 }
1243
1244 if (!last->HasFastProperties()) {
1245 __ lw(scratch2(), FieldMemOperand(reg, HeapObject::kMapOffset));
1246 __ lw(scratch2(), FieldMemOperand(scratch2(), Map::kPrototypeOffset));
1247 __ Branch(&miss, ne, scratch2(),
1248 Operand(isolate()->factory()->null_value()));
1249 }
1250
1251 HandlerFrontendFooter(success, &miss);
1252 }
1253
1254
1255 void BaseLoadStubCompiler::GenerateLoadField(Register reg,
1256 Handle<JSObject> holder,
1257 PropertyIndex index) {
1186 GenerateFastPropertyLoad(masm(), v0, reg, holder, index); 1258 GenerateFastPropertyLoad(masm(), v0, reg, holder, index);
1187 __ Ret(); 1259 __ Ret();
1188 } 1260 }
1189 1261
1190 1262
1191 void StubCompiler::GenerateLoadConstant(Handle<JSObject> object, 1263 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, scratch1);
1202
1203 // Check that the maps haven't changed.
1204 CheckPrototypes(object, receiver, holder,
1205 scratch1, scratch2, scratch3, name, miss);
1206
1207 // Return the constant value. 1264 // Return the constant value.
1208 __ LoadHeapObject(v0, value); 1265 __ LoadHeapObject(v0, value);
1209 __ Ret(); 1266 __ Ret();
1210 } 1267 }
1211 1268
1212 1269
1213 void StubCompiler::GenerateDictionaryLoadCallback( 1270 void BaseLoadStubCompiler::GenerateLoadCallback(
1214 Register receiver, 1271 Register reg,
1215 Register name_reg, 1272 Handle<ExecutableAccessorInfo> callback) {
1216 Register scratch1,
1217 Register scratch2,
1218 Register scratch3,
1219 Handle<ExecutableAccessorInfo> callback,
1220 Handle<String> name,
1221 Label* miss) {
1222 ASSERT(!receiver.is(scratch1));
1223 ASSERT(!receiver.is(scratch2));
1224 ASSERT(!receiver.is(scratch3));
1225
1226 // Load the properties dictionary.
1227 Register dictionary = scratch1;
1228 __ lw(dictionary, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
1229
1230 // Probe the dictionary.
1231 Label probe_done;
1232 StringDictionaryLookupStub::GeneratePositiveLookup(masm(),
1233 miss,
1234 &probe_done,
1235 dictionary,
1236 name_reg,
1237 scratch2,
1238 scratch3);
1239 __ bind(&probe_done);
1240
1241 // If probing finds an entry in the dictionary, scratch3 contains the
1242 // pointer into the dictionary. Check that the value is the callback.
1243 Register pointer = scratch3;
1244 const int kElementsStartOffset = StringDictionary::kHeaderSize +
1245 StringDictionary::kElementsStartIndex * kPointerSize;
1246 const int kValueOffset = kElementsStartOffset + kPointerSize;
1247 __ lw(scratch2, FieldMemOperand(pointer, kValueOffset));
1248 __ Branch(miss, ne, scratch2, Operand(callback));
1249 }
1250
1251
1252 void StubCompiler::GenerateLoadCallback(
1253 Handle<JSObject> object,
1254 Handle<JSObject> holder,
1255 Register receiver,
1256 Register name_reg,
1257 Register scratch1,
1258 Register scratch2,
1259 Register scratch3,
1260 Register scratch4,
1261 Handle<ExecutableAccessorInfo> callback,
1262 Handle<String> name,
1263 Label* miss) {
1264 // Check that the receiver isn't a smi.
1265 __ JumpIfSmi(receiver, miss, scratch1);
1266
1267 // Check that the maps haven't changed.
1268 Register reg = CheckPrototypes(object, receiver, holder, scratch1,
1269 scratch2, scratch3, name, miss);
1270
1271 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) {
1272 GenerateDictionaryLoadCallback(
1273 reg, name_reg, scratch2, scratch3, scratch4, callback, name, miss);
1274 }
1275
1276 // 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
1277 // 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.
1278 __ push(receiver); 1275 __ push(receiver());
1279 __ mov(scratch2, sp); // scratch2 = AccessorInfo::args_ 1276 __ mov(scratch2(), sp); // scratch2 = AccessorInfo::args_
1280 if (heap()->InNewSpace(callback->data())) { 1277 if (heap()->InNewSpace(callback->data())) {
1281 __ li(scratch3, callback); 1278 __ li(scratch3(), callback);
1282 __ lw(scratch3, 1279 __ lw(scratch3(), FieldMemOperand(scratch3(),
1283 FieldMemOperand(scratch3, ExecutableAccessorInfo::kDataOffset)); 1280 ExecutableAccessorInfo::kDataOffset));
1284 } else { 1281 } else {
1285 __ li(scratch3, Handle<Object>(callback->data(), masm()->isolate())); 1282 __ li(scratch3(), Handle<Object>(callback->data(),
1283 callback->GetIsolate()));
1286 } 1284 }
1287 __ Subu(sp, sp, 4 * kPointerSize); 1285 __ Subu(sp, sp, 4 * kPointerSize);
1288 __ sw(reg, MemOperand(sp, 3 * kPointerSize)); 1286 __ sw(reg, MemOperand(sp, 3 * kPointerSize));
1289 __ sw(scratch3, MemOperand(sp, 2 * kPointerSize)); 1287 __ sw(scratch3(), MemOperand(sp, 2 * kPointerSize));
1290 __ li(scratch3, Operand(ExternalReference::isolate_address())); 1288 __ li(scratch3(), Operand(ExternalReference::isolate_address()));
1291 __ sw(scratch3, MemOperand(sp, 1 * kPointerSize)); 1289 __ sw(scratch3(), MemOperand(sp, 1 * kPointerSize));
1292 __ sw(name_reg, MemOperand(sp, 0 * kPointerSize)); 1290 __ sw(name(), MemOperand(sp, 0 * kPointerSize));
1293 1291
1294 __ mov(a2, scratch2); // Saved in case scratch2 == a1. 1292 __ mov(a2, scratch2()); // Saved in case scratch2 == a1.
1295 __ mov(a1, sp); // a1 (first argument - see note below) = Handle<String> 1293 __ mov(a1, sp); // a1 (first argument - see note below) = Handle<String>
1296 1294
1297 // NOTE: the O32 abi requires a0 to hold a special pointer when returning a 1295 // NOTE: the O32 abi requires a0 to hold a special pointer when returning a
1298 // struct from the function (which is currently the case). This means we pass 1296 // struct from the function (which is currently the case). This means we pass
1299 // the arguments in a1-a2 instead of a0-a1. TryCallApiFunctionAndReturn 1297 // the arguments in a1-a2 instead of a0-a1. TryCallApiFunctionAndReturn
1300 // will handle setting up a0. 1298 // will handle setting up a0.
1301 1299
1302 const int kApiStackSpace = 1; 1300 const int kApiStackSpace = 1;
1303 FrameScope frame_scope(masm(), StackFrame::MANUAL); 1301 FrameScope frame_scope(masm(), StackFrame::MANUAL);
1304 __ EnterExitFrame(false, kApiStackSpace); 1302 __ EnterExitFrame(false, kApiStackSpace);
1305 1303
1306 // Create AccessorInfo instance on the stack above the exit frame with 1304 // Create AccessorInfo instance on the stack above the exit frame with
1307 // scratch2 (internal::Object** args_) as the data. 1305 // scratch2 (internal::Object** args_) as the data.
1308 __ sw(a2, MemOperand(sp, kPointerSize)); 1306 __ sw(a2, MemOperand(sp, kPointerSize));
1309 // a2 (second argument - see note above) = AccessorInfo& 1307 // a2 (second argument - see note above) = AccessorInfo&
1310 __ Addu(a2, sp, kPointerSize); 1308 __ Addu(a2, sp, kPointerSize);
1311 1309
1312 const int kStackUnwindSpace = 5; 1310 const int kStackUnwindSpace = 5;
1313 Address getter_address = v8::ToCData<Address>(callback->getter()); 1311 Address getter_address = v8::ToCData<Address>(callback->getter());
1314 ApiFunction fun(getter_address); 1312 ApiFunction fun(getter_address);
1315 ExternalReference ref = 1313 ExternalReference ref =
1316 ExternalReference(&fun, 1314 ExternalReference(&fun,
1317 ExternalReference::DIRECT_GETTER_CALL, 1315 ExternalReference::DIRECT_GETTER_CALL,
1318 masm()->isolate()); 1316 masm()->isolate());
1319 __ CallApiFunctionAndReturn(ref, kStackUnwindSpace); 1317 __ CallApiFunctionAndReturn(ref, kStackUnwindSpace);
1320 } 1318 }
1321 1319
1322 1320
1323 void StubCompiler::GenerateLoadInterceptor(Handle<JSObject> object, 1321 void BaseLoadStubCompiler::GenerateLoadInterceptor(
1324 Handle<JSObject> interceptor_holder, 1322 Register holder_reg,
1325 LookupResult* lookup, 1323 Handle<JSObject> object,
1326 Register receiver, 1324 Handle<JSObject> interceptor_holder,
1327 Register name_reg, 1325 LookupResult* lookup,
1328 Register scratch1, 1326 Handle<String> name) {
1329 Register scratch2,
1330 Register scratch3,
1331 Handle<String> name,
1332 Label* miss) {
1333 ASSERT(interceptor_holder->HasNamedInterceptor()); 1327 ASSERT(interceptor_holder->HasNamedInterceptor());
1334 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); 1328 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined());
1335 1329
1336 // Check that the receiver isn't a smi.
1337 __ JumpIfSmi(receiver, miss);
1338
1339 // So far the most popular follow ups for interceptor loads are FIELD 1330 // So far the most popular follow ups for interceptor loads are FIELD
1340 // and CALLBACKS, so inline only them, other cases may be added 1331 // and CALLBACKS, so inline only them, other cases may be added
1341 // later. 1332 // later.
1342 bool compile_followup_inline = false; 1333 bool compile_followup_inline = false;
1343 if (lookup->IsFound() && lookup->IsCacheable()) { 1334 if (lookup->IsFound() && lookup->IsCacheable()) {
1344 if (lookup->IsField()) { 1335 if (lookup->IsField()) {
1345 compile_followup_inline = true; 1336 compile_followup_inline = true;
1346 } else if (lookup->type() == CALLBACKS && 1337 } else if (lookup->type() == CALLBACKS &&
1347 lookup->GetCallbackObject()->IsExecutableAccessorInfo()) { 1338 lookup->GetCallbackObject()->IsExecutableAccessorInfo()) {
1348 ExecutableAccessorInfo* callback = 1339 ExecutableAccessorInfo* callback =
1349 ExecutableAccessorInfo::cast(lookup->GetCallbackObject()); 1340 ExecutableAccessorInfo::cast(lookup->GetCallbackObject());
1350 compile_followup_inline = callback->getter() != NULL && 1341 compile_followup_inline = callback->getter() != NULL &&
1351 callback->IsCompatibleReceiver(*object); 1342 callback->IsCompatibleReceiver(*object);
1352 } 1343 }
1353 } 1344 }
1354 1345
1355 if (compile_followup_inline) { 1346 if (compile_followup_inline) {
1356 // Compile the interceptor call, followed by inline code to load the 1347 // Compile the interceptor call, followed by inline code to load the
1357 // property from further up the prototype chain if the call fails. 1348 // property from further up the prototype chain if the call fails.
1358 // Check that the maps haven't changed. 1349 // Check that the maps haven't changed.
1359 Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder, 1350 ASSERT(holder_reg.is(receiver()) || holder_reg.is(scratch1()));
1360 scratch1, scratch2, scratch3,
1361 name, miss);
1362 ASSERT(holder_reg.is(receiver) || holder_reg.is(scratch1));
1363 1351
1364 // Preserve the receiver register explicitly whenever it is different from 1352 // Preserve the receiver register explicitly whenever it is different from
1365 // the holder and it is needed should the interceptor return without any 1353 // the holder and it is needed should the interceptor return without any
1366 // result. The CALLBACKS case needs the receiver to be passed into C++ code, 1354 // result. The CALLBACKS case needs the receiver to be passed into C++ code,
1367 // the FIELD case might cause a miss during the prototype check. 1355 // the FIELD case might cause a miss during the prototype check.
1368 bool must_perfrom_prototype_check = *interceptor_holder != lookup->holder(); 1356 bool must_perfrom_prototype_check = *interceptor_holder != lookup->holder();
1369 bool must_preserve_receiver_reg = !receiver.is(holder_reg) && 1357 bool must_preserve_receiver_reg = !receiver().is(holder_reg) &&
1370 (lookup->type() == CALLBACKS || must_perfrom_prototype_check); 1358 (lookup->type() == CALLBACKS || must_perfrom_prototype_check);
1371 1359
1372 // Save necessary data before invoking an interceptor. 1360 // Save necessary data before invoking an interceptor.
1373 // Requires a frame to make GC aware of pushed pointers. 1361 // Requires a frame to make GC aware of pushed pointers.
1374 { 1362 {
1375 FrameScope frame_scope(masm(), StackFrame::INTERNAL); 1363 FrameScope frame_scope(masm(), StackFrame::INTERNAL);
1376 if (must_preserve_receiver_reg) { 1364 if (must_preserve_receiver_reg) {
1377 __ Push(receiver, holder_reg, name_reg); 1365 __ Push(receiver(), holder_reg, this->name());
1378 } else { 1366 } else {
1379 __ Push(holder_reg, name_reg); 1367 __ Push(holder_reg, this->name());
1380 } 1368 }
1381 // Invoke an interceptor. Note: map checks from receiver to 1369 // Invoke an interceptor. Note: map checks from receiver to
1382 // interceptor's holder has been compiled before (see a caller 1370 // interceptor's holder has been compiled before (see a caller
1383 // of this method). 1371 // of this method).
1384 CompileCallLoadPropertyWithInterceptor(masm(), 1372 CompileCallLoadPropertyWithInterceptor(masm(),
1385 receiver, 1373 receiver(),
1386 holder_reg, 1374 holder_reg,
1387 name_reg, 1375 this->name(),
1388 interceptor_holder); 1376 interceptor_holder);
1389 // Check if interceptor provided a value for property. If it's 1377 // Check if interceptor provided a value for property. If it's
1390 // the case, return immediately. 1378 // the case, return immediately.
1391 Label interceptor_failed; 1379 Label interceptor_failed;
1392 __ LoadRoot(scratch1, Heap::kNoInterceptorResultSentinelRootIndex); 1380 __ LoadRoot(scratch1(), Heap::kNoInterceptorResultSentinelRootIndex);
1393 __ Branch(&interceptor_failed, eq, v0, Operand(scratch1)); 1381 __ Branch(&interceptor_failed, eq, v0, Operand(scratch1()));
1394 frame_scope.GenerateLeaveFrame(); 1382 frame_scope.GenerateLeaveFrame();
1395 __ Ret(); 1383 __ Ret();
1396 1384
1397 __ bind(&interceptor_failed); 1385 __ bind(&interceptor_failed);
1398 __ pop(name_reg); 1386 __ pop(this->name());
1399 __ pop(holder_reg); 1387 __ pop(holder_reg);
1400 if (must_preserve_receiver_reg) { 1388 if (must_preserve_receiver_reg) {
1401 __ pop(receiver); 1389 __ pop(receiver());
1402 } 1390 }
1403 // Leave the internal frame. 1391 // Leave the internal frame.
1404 } 1392 }
1405 // Check that the maps from interceptor's holder to lookup's holder 1393 GenerateLoadPostInterceptor(holder_reg, interceptor_holder, name, lookup);
1406 // haven't changed. And load lookup's holder into |holder| register.
1407 if (must_perfrom_prototype_check) {
1408 holder_reg = CheckPrototypes(interceptor_holder,
1409 holder_reg,
1410 Handle<JSObject>(lookup->holder()),
1411 scratch1,
1412 scratch2,
1413 scratch3,
1414 name,
1415 miss);
1416 }
1417
1418 if (lookup->IsField()) {
1419 // We found FIELD property in prototype chain of interceptor's holder.
1420 // Retrieve a field from field's holder.
1421 GenerateFastPropertyLoad(masm(), v0, holder_reg,
1422 Handle<JSObject>(lookup->holder()),
1423 lookup->GetFieldIndex());
1424 __ Ret();
1425 } else {
1426 // We found CALLBACKS property in prototype chain of interceptor's
1427 // holder.
1428 ASSERT(lookup->type() == CALLBACKS);
1429 Handle<ExecutableAccessorInfo> callback(
1430 ExecutableAccessorInfo::cast(lookup->GetCallbackObject()));
1431 ASSERT(callback->getter() != NULL);
1432
1433 // Tail call to runtime.
1434 // Important invariant in CALLBACKS case: the code above must be
1435 // structured to never clobber |receiver| register.
1436 __ li(scratch2, callback);
1437
1438 __ Push(receiver, holder_reg);
1439 __ lw(scratch3,
1440 FieldMemOperand(scratch2, ExecutableAccessorInfo::kDataOffset));
1441 __ li(scratch1, Operand(ExternalReference::isolate_address()));
1442 __ Push(scratch3, scratch1, scratch2, name_reg);
1443
1444 ExternalReference ref =
1445 ExternalReference(IC_Utility(IC::kLoadCallbackProperty),
1446 masm()->isolate());
1447 __ TailCallExternalReference(ref, 6, 1);
1448 }
1449 } else { // !compile_followup_inline 1394 } else { // !compile_followup_inline
1450 // Call the runtime system to load the interceptor. 1395 // Call the runtime system to load the interceptor.
1451 // Check that the maps haven't changed. 1396 // Check that the maps haven't changed.
1452 Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder, 1397 PushInterceptorArguments(masm(), receiver(), holder_reg,
1453 scratch1, scratch2, scratch3, 1398 this->name(), interceptor_holder);
1454 name, miss);
1455 PushInterceptorArguments(masm(), receiver, holder_reg,
1456 name_reg, interceptor_holder);
1457 1399
1458 ExternalReference ref = ExternalReference( 1400 ExternalReference ref = ExternalReference(
1459 IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), masm()->isolate()); 1401 IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), masm()->isolate());
1460 __ TailCallExternalReference(ref, 6, 1); 1402 __ TailCallExternalReference(ref, 6, 1);
1461 } 1403 }
1462 } 1404 }
1463 1405
1464 1406
1465 void CallStubCompiler::GenerateNameCheck(Handle<String> name, Label* miss) { 1407 void CallStubCompiler::GenerateNameCheck(Handle<String> name, Label* miss) {
1466 if (kind_ == Code::KEYED_CALL_IC) { 1408 if (kind_ == Code::KEYED_CALL_IC) {
(...skipping 1431 matching lines...) Expand 10 before | Expand all | Expand 10 after
2898 // Return the generated code. 2840 // Return the generated code.
2899 return GetCode(Code::NORMAL, name); 2841 return GetCode(Code::NORMAL, name);
2900 } 2842 }
2901 2843
2902 2844
2903 Handle<Code> LoadStubCompiler::CompileLoadNonexistent( 2845 Handle<Code> LoadStubCompiler::CompileLoadNonexistent(
2904 Handle<JSObject> object, 2846 Handle<JSObject> object,
2905 Handle<JSObject> last, 2847 Handle<JSObject> last,
2906 Handle<String> name, 2848 Handle<String> name,
2907 Handle<GlobalObject> global) { 2849 Handle<GlobalObject> global) {
2908 // ----------- S t a t e ------------- 2850 Label success;
2909 // -- a0 : receiver
2910 // -- ra : return address
2911 // -----------------------------------
2912 Label miss;
2913 2851
2914 // Check that the receiver is not a smi. 2852 NonexistentHandlerFrontend(object, last, name, &success, global);
2915 __ JumpIfSmi(a0, &miss);
2916 2853
2917 Register scratch = a1; 2854 __ bind(&success);
2918
2919 // Check the maps of the full prototype chain.
2920 Register result =
2921 CheckPrototypes(object, a0, last, a3, scratch, t0, name, &miss);
2922
2923 // If the last object in the prototype chain is a global object,
2924 // check that the global property cell is empty.
2925 if (!global.is_null()) {
2926 GenerateCheckPropertyCell(masm(), global, name, scratch, &miss);
2927 }
2928
2929 if (!last->HasFastProperties()) {
2930 __ lw(scratch, FieldMemOperand(result, HeapObject::kMapOffset));
2931 __ lw(scratch, FieldMemOperand(scratch, Map::kPrototypeOffset));
2932 __ Branch(&miss, ne, scratch, Operand(isolate()->factory()->null_value()));
2933 }
2934
2935 // Return undefined if maps of the full prototype chain is still the same. 2855 // Return undefined if maps of the full prototype chain is still the same.
2936 __ LoadRoot(v0, Heap::kUndefinedValueRootIndex); 2856 __ LoadRoot(v0, Heap::kUndefinedValueRootIndex);
2937 __ Ret(); 2857 __ Ret();
2938 2858
2939 __ bind(&miss);
2940 GenerateLoadMiss(masm(), Code::LOAD_IC);
2941
2942 // Return the generated code. 2859 // Return the generated code.
2943 return GetCode(Code::NONEXISTENT, factory()->empty_string()); 2860 return GetCode(Code::NONEXISTENT, factory()->empty_string());
2944 } 2861 }
2945 2862
2946 2863
2947 Register* LoadStubCompiler::registers() { 2864 Register* LoadStubCompiler::registers() {
2948 // receiver, name, scratch1, scratch2, scratch3, scratch4. 2865 // receiver, name, scratch1, scratch2, scratch3, scratch4.
2949 static Register registers[] = { a0, a2, a3, a1, t0, t1 }; 2866 static Register registers[] = { a0, a2, a3, a1, t0, t1 };
2950 return registers; 2867 return registers;
2951 } 2868 }
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
2995 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 2912 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
2996 } 2913 }
2997 __ Ret(); 2914 __ Ret();
2998 } 2915 }
2999 2916
3000 2917
3001 #undef __ 2918 #undef __
3002 #define __ ACCESS_MASM(masm()) 2919 #define __ ACCESS_MASM(masm())
3003 2920
3004 2921
3005 Handle<Code> LoadStubCompiler::CompileLoadViaGetter(
3006 Handle<JSObject> receiver,
3007 Handle<JSObject> holder,
3008 Handle<String> name,
3009 Handle<JSFunction> getter) {
3010 // ----------- S t a t e -------------
3011 // -- a0 : receiver
3012 // -- a2 : name
3013 // -- ra : return address
3014 // -----------------------------------
3015 Label miss;
3016
3017 // Check that the maps haven't changed.
3018 __ JumpIfSmi(a0, &miss);
3019 CheckPrototypes(receiver, a0, holder, a3, t0, a1, name, &miss);
3020
3021 GenerateLoadViaGetter(masm(), getter);
3022
3023 __ bind(&miss);
3024 GenerateLoadMiss(masm(), Code::LOAD_IC);
3025
3026 // Return the generated code.
3027 return GetCode(Code::CALLBACKS, name);
3028 }
3029
3030
3031 Handle<Code> LoadStubCompiler::CompileLoadGlobal( 2922 Handle<Code> LoadStubCompiler::CompileLoadGlobal(
3032 Handle<JSObject> object, 2923 Handle<JSObject> object,
3033 Handle<GlobalObject> holder, 2924 Handle<GlobalObject> global,
3034 Handle<JSGlobalPropertyCell> cell, 2925 Handle<JSGlobalPropertyCell> cell,
3035 Handle<String> name, 2926 Handle<String> name,
3036 bool is_dont_delete) { 2927 bool is_dont_delete) {
3037 // ----------- S t a t e ------------- 2928 Label success, miss;
3038 // -- a0 : receiver
3039 // -- a2 : name
3040 // -- ra : return address
3041 // -----------------------------------
3042 Label miss;
3043 2929
3044 // Check that the map of the global has not changed. 2930 HandlerFrontendHeader(object, receiver(), Handle<JSObject>::cast(global),
3045 __ JumpIfSmi(a0, &miss); 2931 name, &miss, PERFORM_INITIAL_CHECKS);
3046 CheckPrototypes(object, a0, holder, a3, t0, a1, name, &miss);
3047 2932
3048 // Get the value from the cell. 2933 // Get the value from the cell.
3049 __ li(a3, Operand(cell)); 2934 __ li(a3, Operand(cell));
3050 __ lw(t0, FieldMemOperand(a3, JSGlobalPropertyCell::kValueOffset)); 2935 __ lw(t0, FieldMemOperand(a3, JSGlobalPropertyCell::kValueOffset));
3051 2936
3052 // Check for deleted property if property can actually be deleted. 2937 // Check for deleted property if property can actually be deleted.
3053 if (!is_dont_delete) { 2938 if (!is_dont_delete) {
3054 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); 2939 __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
3055 __ Branch(&miss, eq, t0, Operand(at)); 2940 __ Branch(&miss, eq, t0, Operand(at));
3056 } 2941 }
3057 2942
3058 __ mov(v0, t0); 2943 HandlerFrontendFooter(&success, &miss);
2944 __ bind(&success);
2945
3059 Counters* counters = masm()->isolate()->counters(); 2946 Counters* counters = masm()->isolate()->counters();
3060 __ IncrementCounter(counters->named_load_global_stub(), 1, a1, a3); 2947 __ IncrementCounter(counters->named_load_global_stub(), 1, a1, a3);
2948 __ mov(v0, t0);
3061 __ Ret(); 2949 __ Ret();
3062 2950
3063 __ bind(&miss);
3064 __ IncrementCounter(counters->named_load_global_stub_miss(), 1, a1, a3);
3065 GenerateLoadMiss(masm(), Code::LOAD_IC);
3066
3067 // Return the generated code. 2951 // Return the generated code.
3068 return GetCode(Code::NORMAL, name); 2952 return GetCode(Code::NORMAL, name);
3069 } 2953 }
3070 2954
3071 2955
3072 Handle<Code> KeyedLoadStubCompiler::CompileLoadElement( 2956 Handle<Code> KeyedLoadStubCompiler::CompileLoadElement(
3073 Handle<Map> receiver_map) { 2957 Handle<Map> receiver_map) {
3074 // ----------- S t a t e ------------- 2958 // ----------- S t a t e -------------
3075 // -- ra : return address 2959 // -- ra : return address
3076 // -- a0 : key 2960 // -- a0 : key
(...skipping 1151 matching lines...) Expand 10 before | Expand all | Expand 10 after
4228 __ Jump(ic_slow, RelocInfo::CODE_TARGET); 4112 __ Jump(ic_slow, RelocInfo::CODE_TARGET);
4229 } 4113 }
4230 } 4114 }
4231 4115
4232 4116
4233 #undef __ 4117 #undef __
4234 4118
4235 } } // namespace v8::internal 4119 } } // namespace v8::internal
4236 4120
4237 #endif // V8_TARGET_ARCH_MIPS 4121 #endif // V8_TARGET_ARCH_MIPS
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698