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 1192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1203 // Check that the maps haven't changed. | 1203 // Check that the maps haven't changed. |
1204 CheckPrototypes(object, receiver, holder, | 1204 CheckPrototypes(object, receiver, holder, |
1205 scratch1, scratch2, scratch3, name, miss); | 1205 scratch1, scratch2, scratch3, name, miss); |
1206 | 1206 |
1207 // Return the constant value. | 1207 // Return the constant value. |
1208 __ LoadHeapObject(v0, value); | 1208 __ LoadHeapObject(v0, value); |
1209 __ Ret(); | 1209 __ Ret(); |
1210 } | 1210 } |
1211 | 1211 |
1212 | 1212 |
1213 void StubCompiler::GenerateDictionaryLoadCallback(Register receiver, | 1213 void StubCompiler::GenerateDictionaryLoadCallback( |
1214 Register name_reg, | 1214 Register receiver, |
1215 Register scratch1, | 1215 Register name_reg, |
1216 Register scratch2, | 1216 Register scratch1, |
1217 Register scratch3, | 1217 Register scratch2, |
1218 Handle<AccessorInfo> callback, | 1218 Register scratch3, |
1219 Handle<String> name, | 1219 Handle<ExecutableAccessorInfo> callback, |
1220 Label* miss) { | 1220 Handle<String> name, |
| 1221 Label* miss) { |
1221 ASSERT(!receiver.is(scratch1)); | 1222 ASSERT(!receiver.is(scratch1)); |
1222 ASSERT(!receiver.is(scratch2)); | 1223 ASSERT(!receiver.is(scratch2)); |
1223 ASSERT(!receiver.is(scratch3)); | 1224 ASSERT(!receiver.is(scratch3)); |
1224 | 1225 |
1225 // Load the properties dictionary. | 1226 // Load the properties dictionary. |
1226 Register dictionary = scratch1; | 1227 Register dictionary = scratch1; |
1227 __ lw(dictionary, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); | 1228 __ lw(dictionary, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); |
1228 | 1229 |
1229 // Probe the dictionary. | 1230 // Probe the dictionary. |
1230 Label probe_done; | 1231 Label probe_done; |
(...skipping 10 matching lines...) Expand all Loading... |
1241 // pointer into the dictionary. Check that the value is the callback. | 1242 // pointer into the dictionary. Check that the value is the callback. |
1242 Register pointer = scratch3; | 1243 Register pointer = scratch3; |
1243 const int kElementsStartOffset = StringDictionary::kHeaderSize + | 1244 const int kElementsStartOffset = StringDictionary::kHeaderSize + |
1244 StringDictionary::kElementsStartIndex * kPointerSize; | 1245 StringDictionary::kElementsStartIndex * kPointerSize; |
1245 const int kValueOffset = kElementsStartOffset + kPointerSize; | 1246 const int kValueOffset = kElementsStartOffset + kPointerSize; |
1246 __ lw(scratch2, FieldMemOperand(pointer, kValueOffset)); | 1247 __ lw(scratch2, FieldMemOperand(pointer, kValueOffset)); |
1247 __ Branch(miss, ne, scratch2, Operand(callback)); | 1248 __ Branch(miss, ne, scratch2, Operand(callback)); |
1248 } | 1249 } |
1249 | 1250 |
1250 | 1251 |
1251 void StubCompiler::GenerateLoadCallback(Handle<JSObject> object, | 1252 void StubCompiler::GenerateLoadCallback( |
1252 Handle<JSObject> holder, | 1253 Handle<JSObject> object, |
1253 Register receiver, | 1254 Handle<JSObject> holder, |
1254 Register name_reg, | 1255 Register receiver, |
1255 Register scratch1, | 1256 Register name_reg, |
1256 Register scratch2, | 1257 Register scratch1, |
1257 Register scratch3, | 1258 Register scratch2, |
1258 Register scratch4, | 1259 Register scratch3, |
1259 Handle<AccessorInfo> callback, | 1260 Register scratch4, |
1260 Handle<String> name, | 1261 Handle<ExecutableAccessorInfo> callback, |
1261 Label* miss) { | 1262 Handle<String> name, |
| 1263 Label* miss) { |
1262 // Check that the receiver isn't a smi. | 1264 // Check that the receiver isn't a smi. |
1263 __ JumpIfSmi(receiver, miss, scratch1); | 1265 __ JumpIfSmi(receiver, miss, scratch1); |
1264 | 1266 |
1265 // Check that the maps haven't changed. | 1267 // Check that the maps haven't changed. |
1266 Register reg = CheckPrototypes(object, receiver, holder, scratch1, | 1268 Register reg = CheckPrototypes(object, receiver, holder, scratch1, |
1267 scratch2, scratch3, name, miss); | 1269 scratch2, scratch3, name, miss); |
1268 | 1270 |
1269 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { | 1271 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { |
1270 GenerateDictionaryLoadCallback( | 1272 GenerateDictionaryLoadCallback( |
1271 reg, name_reg, scratch2, scratch3, scratch4, callback, name, miss); | 1273 reg, name_reg, scratch2, scratch3, scratch4, callback, name, miss); |
1272 } | 1274 } |
1273 | 1275 |
1274 // Build AccessorInfo::args_ list on the stack and push property name below | 1276 // Build AccessorInfo::args_ list on the stack and push property name below |
1275 // the exit frame to make GC aware of them and store pointers to them. | 1277 // the exit frame to make GC aware of them and store pointers to them. |
1276 __ push(receiver); | 1278 __ push(receiver); |
1277 __ mov(scratch2, sp); // scratch2 = AccessorInfo::args_ | 1279 __ mov(scratch2, sp); // scratch2 = AccessorInfo::args_ |
1278 if (heap()->InNewSpace(callback->data())) { | 1280 if (heap()->InNewSpace(callback->data())) { |
1279 __ li(scratch3, callback); | 1281 __ li(scratch3, callback); |
1280 __ lw(scratch3, FieldMemOperand(scratch3, AccessorInfo::kDataOffset)); | 1282 __ lw(scratch3, |
| 1283 FieldMemOperand(scratch3, ExecutableAccessorInfo::kDataOffset)); |
1281 } else { | 1284 } else { |
1282 __ li(scratch3, Handle<Object>(callback->data())); | 1285 __ li(scratch3, Handle<Object>(callback->data())); |
1283 } | 1286 } |
1284 __ Subu(sp, sp, 4 * kPointerSize); | 1287 __ Subu(sp, sp, 4 * kPointerSize); |
1285 __ sw(reg, MemOperand(sp, 3 * kPointerSize)); | 1288 __ sw(reg, MemOperand(sp, 3 * kPointerSize)); |
1286 __ sw(scratch3, MemOperand(sp, 2 * kPointerSize)); | 1289 __ sw(scratch3, MemOperand(sp, 2 * kPointerSize)); |
1287 __ li(scratch3, Operand(ExternalReference::isolate_address())); | 1290 __ li(scratch3, Operand(ExternalReference::isolate_address())); |
1288 __ sw(scratch3, MemOperand(sp, 1 * kPointerSize)); | 1291 __ sw(scratch3, MemOperand(sp, 1 * kPointerSize)); |
1289 __ sw(name_reg, MemOperand(sp, 0 * kPointerSize)); | 1292 __ sw(name_reg, MemOperand(sp, 0 * kPointerSize)); |
1290 | 1293 |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1334 __ JumpIfSmi(receiver, miss); | 1337 __ JumpIfSmi(receiver, miss); |
1335 | 1338 |
1336 // So far the most popular follow ups for interceptor loads are FIELD | 1339 // So far the most popular follow ups for interceptor loads are FIELD |
1337 // and CALLBACKS, so inline only them, other cases may be added | 1340 // and CALLBACKS, so inline only them, other cases may be added |
1338 // later. | 1341 // later. |
1339 bool compile_followup_inline = false; | 1342 bool compile_followup_inline = false; |
1340 if (lookup->IsFound() && lookup->IsCacheable()) { | 1343 if (lookup->IsFound() && lookup->IsCacheable()) { |
1341 if (lookup->IsField()) { | 1344 if (lookup->IsField()) { |
1342 compile_followup_inline = true; | 1345 compile_followup_inline = true; |
1343 } else if (lookup->type() == CALLBACKS && | 1346 } else if (lookup->type() == CALLBACKS && |
1344 lookup->GetCallbackObject()->IsAccessorInfo()) { | 1347 lookup->GetCallbackObject()->IsExecutableAccessorInfo()) { |
1345 AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject()); | 1348 ExecutableAccessorInfo* callback = |
| 1349 ExecutableAccessorInfo::cast(lookup->GetCallbackObject()); |
1346 compile_followup_inline = callback->getter() != NULL && | 1350 compile_followup_inline = callback->getter() != NULL && |
1347 callback->IsCompatibleReceiver(*object); | 1351 callback->IsCompatibleReceiver(*object); |
1348 } | 1352 } |
1349 } | 1353 } |
1350 | 1354 |
1351 if (compile_followup_inline) { | 1355 if (compile_followup_inline) { |
1352 // Compile the interceptor call, followed by inline code to load the | 1356 // Compile the interceptor call, followed by inline code to load the |
1353 // property from further up the prototype chain if the call fails. | 1357 // property from further up the prototype chain if the call fails. |
1354 // Check that the maps haven't changed. | 1358 // Check that the maps haven't changed. |
1355 Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder, | 1359 Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder, |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1415 // We found FIELD property in prototype chain of interceptor's holder. | 1419 // We found FIELD property in prototype chain of interceptor's holder. |
1416 // Retrieve a field from field's holder. | 1420 // Retrieve a field from field's holder. |
1417 GenerateFastPropertyLoad(masm(), v0, holder_reg, | 1421 GenerateFastPropertyLoad(masm(), v0, holder_reg, |
1418 Handle<JSObject>(lookup->holder()), | 1422 Handle<JSObject>(lookup->holder()), |
1419 lookup->GetFieldIndex()); | 1423 lookup->GetFieldIndex()); |
1420 __ Ret(); | 1424 __ Ret(); |
1421 } else { | 1425 } else { |
1422 // We found CALLBACKS property in prototype chain of interceptor's | 1426 // We found CALLBACKS property in prototype chain of interceptor's |
1423 // holder. | 1427 // holder. |
1424 ASSERT(lookup->type() == CALLBACKS); | 1428 ASSERT(lookup->type() == CALLBACKS); |
1425 Handle<AccessorInfo> callback( | 1429 Handle<ExecutableAccessorInfo> callback( |
1426 AccessorInfo::cast(lookup->GetCallbackObject())); | 1430 ExecutableAccessorInfo::cast(lookup->GetCallbackObject())); |
1427 ASSERT(callback->getter() != NULL); | 1431 ASSERT(callback->getter() != NULL); |
1428 | 1432 |
1429 // Tail call to runtime. | 1433 // Tail call to runtime. |
1430 // Important invariant in CALLBACKS case: the code above must be | 1434 // Important invariant in CALLBACKS case: the code above must be |
1431 // structured to never clobber |receiver| register. | 1435 // structured to never clobber |receiver| register. |
1432 __ li(scratch2, callback); | 1436 __ li(scratch2, callback); |
1433 | 1437 |
1434 __ Push(receiver, holder_reg); | 1438 __ Push(receiver, holder_reg); |
1435 __ lw(scratch3, | 1439 __ lw(scratch3, |
1436 FieldMemOperand(scratch2, AccessorInfo::kDataOffset)); | 1440 FieldMemOperand(scratch2, ExecutableAccessorInfo::kDataOffset)); |
1437 __ li(scratch1, Operand(ExternalReference::isolate_address())); | 1441 __ li(scratch1, Operand(ExternalReference::isolate_address())); |
1438 __ Push(scratch3, scratch1, scratch2, name_reg); | 1442 __ Push(scratch3, scratch1, scratch2, name_reg); |
1439 | 1443 |
1440 ExternalReference ref = | 1444 ExternalReference ref = |
1441 ExternalReference(IC_Utility(IC::kLoadCallbackProperty), | 1445 ExternalReference(IC_Utility(IC::kLoadCallbackProperty), |
1442 masm()->isolate()); | 1446 masm()->isolate()); |
1443 __ TailCallExternalReference(ref, 6, 1); | 1447 __ TailCallExternalReference(ref, 6, 1); |
1444 } | 1448 } |
1445 } else { // !compile_followup_inline | 1449 } else { // !compile_followup_inline |
1446 // Call the runtime system to load the interceptor. | 1450 // Call the runtime system to load the interceptor. |
(...skipping 1240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2687 return GetCode(transition.is_null() | 2691 return GetCode(transition.is_null() |
2688 ? Code::FIELD | 2692 ? Code::FIELD |
2689 : Code::MAP_TRANSITION, name); | 2693 : Code::MAP_TRANSITION, name); |
2690 } | 2694 } |
2691 | 2695 |
2692 | 2696 |
2693 Handle<Code> StoreStubCompiler::CompileStoreCallback( | 2697 Handle<Code> StoreStubCompiler::CompileStoreCallback( |
2694 Handle<String> name, | 2698 Handle<String> name, |
2695 Handle<JSObject> receiver, | 2699 Handle<JSObject> receiver, |
2696 Handle<JSObject> holder, | 2700 Handle<JSObject> holder, |
2697 Handle<AccessorInfo> callback) { | 2701 Handle<ExecutableAccessorInfo> callback) { |
2698 // ----------- S t a t e ------------- | 2702 // ----------- S t a t e ------------- |
2699 // -- a0 : value | 2703 // -- a0 : value |
2700 // -- a1 : receiver | 2704 // -- a1 : receiver |
2701 // -- a2 : name | 2705 // -- a2 : name |
2702 // -- ra : return address | 2706 // -- ra : return address |
2703 // ----------------------------------- | 2707 // ----------------------------------- |
2704 Label miss; | 2708 Label miss; |
2705 // Check that the maps haven't changed. | 2709 // Check that the maps haven't changed. |
2706 __ JumpIfSmi(a1, &miss, a3); | 2710 __ JumpIfSmi(a1, &miss, a3); |
2707 CheckPrototypes(receiver, a1, holder, a3, t0, t1, name, &miss); | 2711 CheckPrototypes(receiver, a1, holder, a3, t0, t1, name, &miss); |
(...skipping 1511 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4219 __ Jump(ic_slow, RelocInfo::CODE_TARGET); | 4223 __ Jump(ic_slow, RelocInfo::CODE_TARGET); |
4220 } | 4224 } |
4221 } | 4225 } |
4222 | 4226 |
4223 | 4227 |
4224 #undef __ | 4228 #undef __ |
4225 | 4229 |
4226 } } // namespace v8::internal | 4230 } } // namespace v8::internal |
4227 | 4231 |
4228 #endif // V8_TARGET_ARCH_MIPS | 4232 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |