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 1048 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1059 // Check the prototype chain. | 1059 // Check the prototype chain. |
1060 Register reg = CheckPrototypes( | 1060 Register reg = CheckPrototypes( |
1061 object, receiver, holder, scratch1, scratch2, scratch3, name, miss); | 1061 object, receiver, holder, scratch1, scratch2, scratch3, name, miss); |
1062 | 1062 |
1063 // Get the value from the properties. | 1063 // Get the value from the properties. |
1064 GenerateFastPropertyLoad(masm(), eax, reg, holder, index); | 1064 GenerateFastPropertyLoad(masm(), eax, reg, holder, index); |
1065 __ ret(0); | 1065 __ ret(0); |
1066 } | 1066 } |
1067 | 1067 |
1068 | 1068 |
1069 void StubCompiler::GenerateDictionaryLoadCallback(Register receiver, | 1069 void StubCompiler::GenerateDictionaryLoadCallback( |
1070 Register name_reg, | 1070 Register receiver, |
1071 Register scratch1, | 1071 Register name_reg, |
1072 Register scratch2, | 1072 Register scratch1, |
1073 Register scratch3, | 1073 Register scratch2, |
1074 Handle<AccessorInfo> callback, | 1074 Register scratch3, |
1075 Handle<String> name, | 1075 Handle<ExecutableAccessorInfo> callback, |
1076 Label* miss) { | 1076 Handle<String> name, |
| 1077 Label* miss) { |
1077 ASSERT(!receiver.is(scratch2)); | 1078 ASSERT(!receiver.is(scratch2)); |
1078 ASSERT(!receiver.is(scratch3)); | 1079 ASSERT(!receiver.is(scratch3)); |
1079 Register dictionary = scratch1; | 1080 Register dictionary = scratch1; |
1080 bool must_preserve_dictionary_reg = receiver.is(dictionary); | 1081 bool must_preserve_dictionary_reg = receiver.is(dictionary); |
1081 | 1082 |
1082 // Load the properties dictionary. | 1083 // Load the properties dictionary. |
1083 if (must_preserve_dictionary_reg) { | 1084 if (must_preserve_dictionary_reg) { |
1084 __ push(dictionary); | 1085 __ push(dictionary); |
1085 } | 1086 } |
1086 __ mov(dictionary, FieldOperand(receiver, JSObject::kPropertiesOffset)); | 1087 __ mov(dictionary, FieldOperand(receiver, JSObject::kPropertiesOffset)); |
(...skipping 24 matching lines...) Expand all Loading... |
1111 __ mov(scratch3, | 1112 __ mov(scratch3, |
1112 Operand(dictionary, index, times_4, kValueOffset - kHeapObjectTag)); | 1113 Operand(dictionary, index, times_4, kValueOffset - kHeapObjectTag)); |
1113 if (must_preserve_dictionary_reg) { | 1114 if (must_preserve_dictionary_reg) { |
1114 __ pop(dictionary); | 1115 __ pop(dictionary); |
1115 } | 1116 } |
1116 __ cmp(scratch3, callback); | 1117 __ cmp(scratch3, callback); |
1117 __ j(not_equal, miss); | 1118 __ j(not_equal, miss); |
1118 } | 1119 } |
1119 | 1120 |
1120 | 1121 |
1121 void StubCompiler::GenerateLoadCallback(Handle<JSObject> object, | 1122 void StubCompiler::GenerateLoadCallback( |
1122 Handle<JSObject> holder, | 1123 Handle<JSObject> object, |
1123 Register receiver, | 1124 Handle<JSObject> holder, |
1124 Register name_reg, | 1125 Register receiver, |
1125 Register scratch1, | 1126 Register name_reg, |
1126 Register scratch2, | 1127 Register scratch1, |
1127 Register scratch3, | 1128 Register scratch2, |
1128 Register scratch4, | 1129 Register scratch3, |
1129 Handle<AccessorInfo> callback, | 1130 Register scratch4, |
1130 Handle<String> name, | 1131 Handle<ExecutableAccessorInfo> callback, |
1131 Label* miss) { | 1132 Handle<String> name, |
| 1133 Label* miss) { |
1132 // Check that the receiver isn't a smi. | 1134 // Check that the receiver isn't a smi. |
1133 __ JumpIfSmi(receiver, miss); | 1135 __ JumpIfSmi(receiver, miss); |
1134 | 1136 |
1135 // Check that the maps haven't changed. | 1137 // Check that the maps haven't changed. |
1136 Register reg = CheckPrototypes(object, receiver, holder, scratch1, | 1138 Register reg = CheckPrototypes(object, receiver, holder, scratch1, |
1137 scratch2, scratch3, name, miss); | 1139 scratch2, scratch3, name, miss); |
1138 | 1140 |
1139 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { | 1141 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { |
1140 GenerateDictionaryLoadCallback( | 1142 GenerateDictionaryLoadCallback( |
1141 reg, name_reg, scratch1, scratch2, scratch3, callback, name, miss); | 1143 reg, name_reg, scratch1, scratch2, scratch3, callback, name, miss); |
1142 } | 1144 } |
1143 | 1145 |
1144 // Insert additional parameters into the stack frame above return address. | 1146 // Insert additional parameters into the stack frame above return address. |
1145 ASSERT(!scratch3.is(reg)); | 1147 ASSERT(!scratch3.is(reg)); |
1146 __ pop(scratch3); // Get return address to place it below. | 1148 __ pop(scratch3); // Get return address to place it below. |
1147 | 1149 |
1148 __ push(receiver); // receiver | 1150 __ push(receiver); // receiver |
1149 __ mov(scratch2, esp); | 1151 __ mov(scratch2, esp); |
1150 ASSERT(!scratch2.is(reg)); | 1152 ASSERT(!scratch2.is(reg)); |
1151 __ push(reg); // holder | 1153 __ push(reg); // holder |
1152 // Push data from AccessorInfo. | 1154 // Push data from AccessorInfo. |
1153 if (isolate()->heap()->InNewSpace(callback->data())) { | 1155 if (isolate()->heap()->InNewSpace(callback->data())) { |
1154 __ mov(scratch1, Immediate(callback)); | 1156 __ mov(scratch1, Immediate(callback)); |
1155 __ push(FieldOperand(scratch1, AccessorInfo::kDataOffset)); | 1157 __ push(FieldOperand(scratch1, ExecutableAccessorInfo::kDataOffset)); |
1156 } else { | 1158 } else { |
1157 __ push(Immediate(Handle<Object>(callback->data()))); | 1159 __ push(Immediate(Handle<Object>(callback->data()))); |
1158 } | 1160 } |
1159 __ push(Immediate(reinterpret_cast<int>(isolate()))); | 1161 __ push(Immediate(reinterpret_cast<int>(isolate()))); |
1160 | 1162 |
1161 // Save a pointer to where we pushed the arguments pointer. | 1163 // Save a pointer to where we pushed the arguments pointer. |
1162 // This will be passed as the const AccessorInfo& to the C++ callback. | 1164 // This will be passed as the const AccessorInfo& to the C++ callback. |
1163 __ push(scratch2); | 1165 __ push(scratch2); |
1164 | 1166 |
1165 __ push(name_reg); // name | 1167 __ push(name_reg); // name |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1225 __ JumpIfSmi(receiver, miss); | 1227 __ JumpIfSmi(receiver, miss); |
1226 | 1228 |
1227 // So far the most popular follow ups for interceptor loads are FIELD | 1229 // So far the most popular follow ups for interceptor loads are FIELD |
1228 // and CALLBACKS, so inline only them, other cases may be added | 1230 // and CALLBACKS, so inline only them, other cases may be added |
1229 // later. | 1231 // later. |
1230 bool compile_followup_inline = false; | 1232 bool compile_followup_inline = false; |
1231 if (lookup->IsFound() && lookup->IsCacheable()) { | 1233 if (lookup->IsFound() && lookup->IsCacheable()) { |
1232 if (lookup->IsField()) { | 1234 if (lookup->IsField()) { |
1233 compile_followup_inline = true; | 1235 compile_followup_inline = true; |
1234 } else if (lookup->type() == CALLBACKS && | 1236 } else if (lookup->type() == CALLBACKS && |
1235 lookup->GetCallbackObject()->IsAccessorInfo()) { | 1237 lookup->GetCallbackObject()->IsExecutableAccessorInfo()) { |
1236 AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject()); | 1238 ExecutableAccessorInfo* callback = |
| 1239 ExecutableAccessorInfo::cast(lookup->GetCallbackObject()); |
1237 compile_followup_inline = callback->getter() != NULL && | 1240 compile_followup_inline = callback->getter() != NULL && |
1238 callback->IsCompatibleReceiver(*object); | 1241 callback->IsCompatibleReceiver(*object); |
1239 } | 1242 } |
1240 } | 1243 } |
1241 | 1244 |
1242 if (compile_followup_inline) { | 1245 if (compile_followup_inline) { |
1243 // Compile the interceptor call, followed by inline code to load the | 1246 // Compile the interceptor call, followed by inline code to load the |
1244 // property from further up the prototype chain if the call fails. | 1247 // property from further up the prototype chain if the call fails. |
1245 // Check that the maps haven't changed. | 1248 // Check that the maps haven't changed. |
1246 Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder, | 1249 Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder, |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1318 // We found FIELD property in prototype chain of interceptor's holder. | 1321 // We found FIELD property in prototype chain of interceptor's holder. |
1319 // Retrieve a field from field's holder. | 1322 // Retrieve a field from field's holder. |
1320 GenerateFastPropertyLoad(masm(), eax, holder_reg, | 1323 GenerateFastPropertyLoad(masm(), eax, holder_reg, |
1321 Handle<JSObject>(lookup->holder()), | 1324 Handle<JSObject>(lookup->holder()), |
1322 lookup->GetFieldIndex()); | 1325 lookup->GetFieldIndex()); |
1323 __ ret(0); | 1326 __ ret(0); |
1324 } else { | 1327 } else { |
1325 // We found CALLBACKS property in prototype chain of interceptor's | 1328 // We found CALLBACKS property in prototype chain of interceptor's |
1326 // holder. | 1329 // holder. |
1327 ASSERT(lookup->type() == CALLBACKS); | 1330 ASSERT(lookup->type() == CALLBACKS); |
1328 Handle<AccessorInfo> callback( | 1331 Handle<ExecutableAccessorInfo> callback( |
1329 AccessorInfo::cast(lookup->GetCallbackObject())); | 1332 ExecutableAccessorInfo::cast(lookup->GetCallbackObject())); |
1330 ASSERT(callback->getter() != NULL); | 1333 ASSERT(callback->getter() != NULL); |
1331 | 1334 |
1332 // Tail call to runtime. | 1335 // Tail call to runtime. |
1333 // Important invariant in CALLBACKS case: the code above must be | 1336 // Important invariant in CALLBACKS case: the code above must be |
1334 // structured to never clobber |receiver| register. | 1337 // structured to never clobber |receiver| register. |
1335 __ pop(scratch2); // return address | 1338 __ pop(scratch2); // return address |
1336 __ push(receiver); | 1339 __ push(receiver); |
1337 __ push(holder_reg); | 1340 __ push(holder_reg); |
1338 __ mov(holder_reg, Immediate(callback)); | 1341 __ mov(holder_reg, Immediate(callback)); |
1339 __ push(FieldOperand(holder_reg, AccessorInfo::kDataOffset)); | 1342 __ push(FieldOperand(holder_reg, ExecutableAccessorInfo::kDataOffset)); |
1340 __ push(Immediate(reinterpret_cast<int>(isolate()))); | 1343 __ push(Immediate(reinterpret_cast<int>(isolate()))); |
1341 __ push(holder_reg); | 1344 __ push(holder_reg); |
1342 __ push(name_reg); | 1345 __ push(name_reg); |
1343 __ push(scratch2); // restore return address | 1346 __ push(scratch2); // restore return address |
1344 | 1347 |
1345 ExternalReference ref = | 1348 ExternalReference ref = |
1346 ExternalReference(IC_Utility(IC::kLoadCallbackProperty), | 1349 ExternalReference(IC_Utility(IC::kLoadCallbackProperty), |
1347 masm()->isolate()); | 1350 masm()->isolate()); |
1348 __ TailCallExternalReference(ref, 6, 1); | 1351 __ TailCallExternalReference(ref, 6, 1); |
1349 } | 1352 } |
(...skipping 1297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2647 return GetCode(transition.is_null() | 2650 return GetCode(transition.is_null() |
2648 ? Code::FIELD | 2651 ? Code::FIELD |
2649 : Code::MAP_TRANSITION, name); | 2652 : Code::MAP_TRANSITION, name); |
2650 } | 2653 } |
2651 | 2654 |
2652 | 2655 |
2653 Handle<Code> StoreStubCompiler::CompileStoreCallback( | 2656 Handle<Code> StoreStubCompiler::CompileStoreCallback( |
2654 Handle<String> name, | 2657 Handle<String> name, |
2655 Handle<JSObject> receiver, | 2658 Handle<JSObject> receiver, |
2656 Handle<JSObject> holder, | 2659 Handle<JSObject> holder, |
2657 Handle<AccessorInfo> callback) { | 2660 Handle<ExecutableAccessorInfo> callback) { |
2658 // ----------- S t a t e ------------- | 2661 // ----------- S t a t e ------------- |
2659 // -- eax : value | 2662 // -- eax : value |
2660 // -- ecx : name | 2663 // -- ecx : name |
2661 // -- edx : receiver | 2664 // -- edx : receiver |
2662 // -- esp[0] : return address | 2665 // -- esp[0] : return address |
2663 // ----------------------------------- | 2666 // ----------------------------------- |
2664 Label miss; | 2667 Label miss; |
2665 // Check that the maps haven't changed, preserving the value register. | 2668 // Check that the maps haven't changed, preserving the value register. |
2666 __ push(eax); | 2669 __ push(eax); |
2667 __ JumpIfSmi(edx, &miss); | 2670 __ JumpIfSmi(edx, &miss); |
(...skipping 1249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3917 __ jmp(ic_slow, RelocInfo::CODE_TARGET); | 3920 __ jmp(ic_slow, RelocInfo::CODE_TARGET); |
3918 } | 3921 } |
3919 } | 3922 } |
3920 | 3923 |
3921 | 3924 |
3922 #undef __ | 3925 #undef __ |
3923 | 3926 |
3924 } } // namespace v8::internal | 3927 } } // namespace v8::internal |
3925 | 3928 |
3926 #endif // V8_TARGET_ARCH_IA32 | 3929 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |