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/ia32/stub-cache-ia32.cc

Issue 12209021: Refactor LoadIC into Handler Frontend and Backends. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: 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/ic.h » ('j') | src/stub-cache.h » ('J')
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 1026 matching lines...) Expand 10 before | Expand all | Expand 10 after
1037 // If we've skipped any global objects, it's not enough to verify that 1037 // If we've skipped any global objects, it's not enough to verify that
1038 // their maps haven't changed. We also need to check that the property 1038 // their maps haven't changed. We also need to check that the property
1039 // cell for the property is still empty. 1039 // cell for the property is still empty.
1040 GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss); 1040 GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss);
1041 1041
1042 // Return the register containing the holder. 1042 // Return the register containing the holder.
1043 return reg; 1043 return reg;
1044 } 1044 }
1045 1045
1046 1046
1047 void StubCompiler::GenerateLoadField(Handle<JSObject> object, 1047 void BaseLoadStubCompiler::GenerateDictionaryLoadCallback(
Toon Verwaest 2013/02/06 14:06:30 This got moved into CallbackHandlerFrontend direct
1048 Handle<JSObject> holder, 1048 Register reg,
1049 Register receiver, 1049 Handle<AccessorInfo> callback,
1050 Register scratch1, 1050 Label* miss) {
1051 Register scratch2, 1051 ASSERT(!reg.is(scratch2()));
1052 Register scratch3, 1052 ASSERT(!reg.is(scratch3()));
1053 PropertyIndex index, 1053 Register dictionary = scratch1();
1054 Handle<String> name, 1054 bool must_preserve_dictionary_reg = reg.is(dictionary);
1055 Label* miss) {
1056 // Check that the receiver isn't a smi.
1057 __ JumpIfSmi(receiver, miss);
1058
1059 // Check the prototype chain.
1060 Register reg = CheckPrototypes(
1061 object, receiver, holder, scratch1, scratch2, scratch3, name, miss);
1062
1063 // Get the value from the properties.
1064 GenerateFastPropertyLoad(masm(), eax, reg, holder, index);
1065 __ ret(0);
1066 }
1067
1068
1069 void StubCompiler::GenerateDictionaryLoadCallback(Register receiver,
1070 Register name_reg,
1071 Register scratch1,
1072 Register scratch2,
1073 Register scratch3,
1074 Handle<AccessorInfo> callback,
1075 Handle<String> name,
1076 Label* miss) {
1077 ASSERT(!receiver.is(scratch2));
1078 ASSERT(!receiver.is(scratch3));
1079 Register dictionary = scratch1;
1080 bool must_preserve_dictionary_reg = receiver.is(dictionary);
1081 1055
1082 // Load the properties dictionary. 1056 // Load the properties dictionary.
1083 if (must_preserve_dictionary_reg) { 1057 if (must_preserve_dictionary_reg) {
1084 __ push(dictionary); 1058 __ push(dictionary);
1085 } 1059 }
1086 __ mov(dictionary, FieldOperand(receiver, JSObject::kPropertiesOffset)); 1060 __ mov(dictionary, FieldOperand(reg, JSObject::kPropertiesOffset));
1087 1061
1088 // Probe the dictionary. 1062 // Probe the dictionary.
1089 Label probe_done, pop_and_miss; 1063 Label probe_done, pop_and_miss;
1090 StringDictionaryLookupStub::GeneratePositiveLookup(masm(), 1064 StringDictionaryLookupStub::GeneratePositiveLookup(masm(),
1091 &pop_and_miss, 1065 &pop_and_miss,
1092 &probe_done, 1066 &probe_done,
1093 dictionary, 1067 dictionary,
1094 name_reg, 1068 this->name(),
1095 scratch2, 1069 scratch2(),
1096 scratch3); 1070 scratch3());
1097 __ bind(&pop_and_miss); 1071 __ bind(&pop_and_miss);
1098 if (must_preserve_dictionary_reg) { 1072 if (must_preserve_dictionary_reg) {
1099 __ pop(dictionary); 1073 __ pop(dictionary);
1100 } 1074 }
1101 __ jmp(miss); 1075 __ jmp(miss);
1102 __ bind(&probe_done); 1076 __ bind(&probe_done);
1103 1077
1104 // If probing finds an entry in the dictionary, scratch2 contains the 1078 // If probing finds an entry in the dictionary, scratch2 contains the
1105 // index into the dictionary. Check that the value is the callback. 1079 // index into the dictionary. Check that the value is the callback.
1106 Register index = scratch2; 1080 Register index = scratch2();
1107 const int kElementsStartOffset = 1081 const int kElementsStartOffset =
1108 StringDictionary::kHeaderSize + 1082 StringDictionary::kHeaderSize +
1109 StringDictionary::kElementsStartIndex * kPointerSize; 1083 StringDictionary::kElementsStartIndex * kPointerSize;
1110 const int kValueOffset = kElementsStartOffset + kPointerSize; 1084 const int kValueOffset = kElementsStartOffset + kPointerSize;
1111 __ mov(scratch3, 1085 __ mov(scratch3(),
1112 Operand(dictionary, index, times_4, kValueOffset - kHeapObjectTag)); 1086 Operand(dictionary, index, times_4, kValueOffset - kHeapObjectTag));
1113 if (must_preserve_dictionary_reg) { 1087 if (must_preserve_dictionary_reg) {
1114 __ pop(dictionary); 1088 __ pop(dictionary);
1115 } 1089 }
1116 __ cmp(scratch3, callback); 1090 __ cmp(scratch3(), callback);
1117 __ j(not_equal, miss); 1091 __ j(not_equal, miss);
1118 } 1092 }
1119 1093
1120 1094
1121 void StubCompiler::GenerateLoadCallback(Handle<JSObject> object, 1095 Register BaseLoadStubCompiler::GenerateHandlerFrontend(
1122 Handle<JSObject> holder, 1096 Handle<JSObject> object,
1123 Register receiver, 1097 Register object_reg,
1124 Register name_reg, 1098 Handle<JSObject> holder,
1125 Register scratch1, 1099 Handle<String> name,
1126 Register scratch2, 1100 Label* success,
1127 Register scratch3, 1101 Handle<AccessorInfo> callback,
1128 Register scratch4, 1102 bool perform_initial_checks) {
1129 Handle<AccessorInfo> callback, 1103 Label miss;
1130 Handle<String> name,
1131 Label* miss) {
1132 // Check that the receiver isn't a smi.
1133 __ JumpIfSmi(receiver, miss);
1134 1104
1135 // Check that the maps haven't changed. 1105 if (perform_initial_checks) {
1136 Register reg = CheckPrototypes(object, receiver, holder, scratch1, 1106 GenerateNameCheck(name, this->name(), &miss);
1137 scratch2, scratch3, name, miss); 1107 // Check that the receiver isn't a smi.
1138 1108 __ JumpIfSmi(object_reg, &miss);
1139 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) {
1140 GenerateDictionaryLoadCallback(
1141 reg, name_reg, scratch1, scratch2, scratch3, callback, name, miss);
1142 } 1109 }
1143 1110
1111 // Check the prototype chain.
1112 Register reg = CheckPrototypes(object, object_reg, holder,
1113 scratch1(), scratch2(), scratch3(),
1114 name, &miss);
1115
1116 if (!callback.is_null() &&
1117 !holder->HasFastProperties() &&
1118 !holder->IsJSGlobalObject()) {
1119 GenerateDictionaryLoadCallback(reg, callback, &miss);
1120 }
1121
1122 __ jmp(success);
1123
1124 __ bind(&miss);
1125 GenerateLoadMiss(masm(), kind());
1126 return reg;
1127 }
1128
1129
1130 void BaseLoadStubCompiler::GenerateLoadField(Register reg,
1131 Handle<JSObject> holder,
1132 PropertyIndex index) {
1133 // Get the value from the properties.
1134 GenerateFastPropertyLoad(masm(), eax, reg, holder, index);
1135 __ ret(0);
1136 }
1137
1138
1139 void BaseLoadStubCompiler::GenerateLoadCallback(Register reg,
1140 Handle<AccessorInfo> callback) {
1144 // Insert additional parameters into the stack frame above return address. 1141 // Insert additional parameters into the stack frame above return address.
1145 ASSERT(!scratch3.is(reg)); 1142 ASSERT(!scratch3().is(reg));
1146 __ pop(scratch3); // Get return address to place it below. 1143 __ pop(scratch3()); // Get return address to place it below.
1147 1144
1148 __ push(receiver); // receiver 1145 __ push(receiver()); // receiver
1149 __ mov(scratch2, esp); 1146 __ mov(scratch2(), esp);
1150 ASSERT(!scratch2.is(reg)); 1147 ASSERT(!scratch2().is(reg));
1151 __ push(reg); // holder 1148 __ push(reg); // holder
1152 // Push data from AccessorInfo. 1149 // Push data from AccessorInfo.
1153 if (isolate()->heap()->InNewSpace(callback->data())) { 1150 if (isolate()->heap()->InNewSpace(callback->data())) {
1154 __ mov(scratch1, Immediate(callback)); 1151 __ mov(scratch1(), Immediate(callback));
1155 __ push(FieldOperand(scratch1, AccessorInfo::kDataOffset)); 1152 __ push(FieldOperand(scratch1(), AccessorInfo::kDataOffset));
1156 } else { 1153 } else {
1157 __ push(Immediate(Handle<Object>(callback->data()))); 1154 __ push(Immediate(Handle<Object>(callback->data())));
1158 } 1155 }
1159 __ push(Immediate(reinterpret_cast<int>(isolate()))); 1156 __ push(Immediate(reinterpret_cast<int>(isolate())));
1160 1157
1161 // Save a pointer to where we pushed the arguments pointer. 1158 // Save a pointer to where we pushed the arguments pointer.
1162 // This will be passed as the const AccessorInfo& to the C++ callback. 1159 // This will be passed as the const AccessorInfo& to the C++ callback.
1163 __ push(scratch2); 1160 __ push(scratch2());
1164 1161
1165 __ push(name_reg); // name 1162 __ push(name()); // name
1166 __ mov(ebx, esp); // esp points to reference to name (handler). 1163 __ mov(ebx, esp); // esp points to reference to name (handler).
1167 1164
1168 __ push(scratch3); // Restore return address. 1165 __ push(scratch3()); // Restore return address.
1169 1166
1170 // 4 elements array for v8::Arguments::values_, handler for name and pointer 1167 // 4 elements array for v8::Arguments::values_, handler for name and pointer
1171 // to the values (it considered as smi in GC). 1168 // to the values (it considered as smi in GC).
1172 const int kStackSpace = 6; 1169 const int kStackSpace = 6;
1173 const int kApiArgc = 2; 1170 const int kApiArgc = 2;
1174 1171
1175 __ PrepareCallApiFunction(kApiArgc); 1172 __ PrepareCallApiFunction(kApiArgc);
1176 __ mov(ApiParameterOperand(0), ebx); // name. 1173 __ mov(ApiParameterOperand(0), ebx); // name.
1177 __ add(ebx, Immediate(kPointerSize)); 1174 __ add(ebx, Immediate(kPointerSize));
1178 __ mov(ApiParameterOperand(1), ebx); // arguments pointer. 1175 __ mov(ApiParameterOperand(1), ebx); // arguments pointer.
1179 1176
1180 // Emitting a stub call may try to allocate (if the code is not 1177 // Emitting a stub call may try to allocate (if the code is not
1181 // already generated). Do not allow the assembler to perform a 1178 // already generated). Do not allow the assembler to perform a
1182 // garbage collection but instead return the allocation failure 1179 // garbage collection but instead return the allocation failure
1183 // object. 1180 // object.
1184 Address getter_address = v8::ToCData<Address>(callback->getter()); 1181 Address getter_address = v8::ToCData<Address>(callback->getter());
1185 __ CallApiFunctionAndReturn(getter_address, kStackSpace); 1182 __ CallApiFunctionAndReturn(getter_address, kStackSpace);
1186 } 1183 }
1187 1184
1188 1185
1189 void StubCompiler::GenerateLoadConstant(Handle<JSObject> object, 1186 void BaseLoadStubCompiler::GenerateLoadConstant(Handle<JSFunction> value) {
1190 Handle<JSObject> holder,
1191 Register receiver,
1192 Register scratch1,
1193 Register scratch2,
1194 Register scratch3,
1195 Handle<JSFunction> value,
1196 Handle<String> name,
1197 Label* miss) {
1198 // Check that the receiver isn't a smi.
1199 __ JumpIfSmi(receiver, miss);
1200
1201 // Check that the maps haven't changed.
1202 CheckPrototypes(
1203 object, receiver, holder, scratch1, scratch2, scratch3, name, miss);
1204
1205 // Return the constant value. 1187 // Return the constant value.
1206 __ LoadHeapObject(eax, value); 1188 __ LoadHeapObject(eax, value);
1207 __ ret(0); 1189 __ ret(0);
1208 } 1190 }
1209 1191
1210 1192
1211 void StubCompiler::GenerateLoadInterceptor(Handle<JSObject> object, 1193 void BaseLoadStubCompiler::GenerateLoadInterceptor(
1212 Handle<JSObject> interceptor_holder, 1194 Register holder_reg,
1213 LookupResult* lookup, 1195 Handle<JSObject> object,
1214 Register receiver, 1196 Handle<JSObject> interceptor_holder,
1215 Register name_reg, 1197 LookupResult* lookup,
1216 Register scratch1, 1198 Handle<String> name) {
1217 Register scratch2,
1218 Register scratch3,
1219 Handle<String> name,
1220 Label* miss) {
1221 ASSERT(interceptor_holder->HasNamedInterceptor()); 1199 ASSERT(interceptor_holder->HasNamedInterceptor());
1222 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); 1200 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined());
1223 1201
1224 // Check that the receiver isn't a smi.
1225 __ JumpIfSmi(receiver, miss);
1226
1227 // So far the most popular follow ups for interceptor loads are FIELD 1202 // So far the most popular follow ups for interceptor loads are FIELD
1228 // and CALLBACKS, so inline only them, other cases may be added 1203 // and CALLBACKS, so inline only them, other cases may be added
1229 // later. 1204 // later.
1230 bool compile_followup_inline = false; 1205 bool compile_followup_inline = false;
1231 if (lookup->IsFound() && lookup->IsCacheable()) { 1206 if (lookup->IsFound() && lookup->IsCacheable()) {
1232 if (lookup->IsField()) { 1207 if (lookup->IsField()) {
1233 compile_followup_inline = true; 1208 compile_followup_inline = true;
1234 } else if (lookup->type() == CALLBACKS && 1209 } else if (lookup->type() == CALLBACKS &&
1235 lookup->GetCallbackObject()->IsAccessorInfo()) { 1210 lookup->GetCallbackObject()->IsAccessorInfo()) {
1236 AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject()); 1211 AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject());
1237 compile_followup_inline = callback->getter() != NULL && 1212 compile_followup_inline = callback->getter() != NULL &&
1238 callback->IsCompatibleReceiver(*object); 1213 callback->IsCompatibleReceiver(*object);
1239 } 1214 }
1240 } 1215 }
1241 1216
1242 if (compile_followup_inline) { 1217 if (compile_followup_inline) {
1243 // Compile the interceptor call, followed by inline code to load the 1218 // Compile the interceptor call, followed by inline code to load the
1244 // property from further up the prototype chain if the call fails. 1219 // property from further up the prototype chain if the call fails.
1245 // Check that the maps haven't changed. 1220 // Check that the maps haven't changed.
1246 Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder, 1221 ASSERT(holder_reg.is(receiver()) || holder_reg.is(scratch1()));
1247 scratch1, scratch2, scratch3,
1248 name, miss);
1249 ASSERT(holder_reg.is(receiver) || holder_reg.is(scratch1));
1250 1222
1251 // Preserve the receiver register explicitly whenever it is different from 1223 // Preserve the receiver register explicitly whenever it is different from
1252 // the holder and it is needed should the interceptor return without any 1224 // the holder and it is needed should the interceptor return without any
1253 // result. The CALLBACKS case needs the receiver to be passed into C++ code, 1225 // result. The CALLBACKS case needs the receiver to be passed into C++ code,
1254 // the FIELD case might cause a miss during the prototype check. 1226 // the FIELD case might cause a miss during the prototype check.
1255 bool must_perfrom_prototype_check = *interceptor_holder != lookup->holder(); 1227 bool must_perfrom_prototype_check = *interceptor_holder != lookup->holder();
Jakob Kummerow 2013/02/06 12:48:27 While you're at it: s/perfrom/perform/
1256 bool must_preserve_receiver_reg = !receiver.is(holder_reg) && 1228 bool must_preserve_receiver_reg = !receiver().is(holder_reg) &&
1257 (lookup->type() == CALLBACKS || must_perfrom_prototype_check); 1229 (lookup->type() == CALLBACKS || must_perfrom_prototype_check);
1258 1230
1259 // Save necessary data before invoking an interceptor. 1231 // Save necessary data before invoking an interceptor.
1260 // Requires a frame to make GC aware of pushed pointers. 1232 // Requires a frame to make GC aware of pushed pointers.
1261 { 1233 {
1262 FrameScope frame_scope(masm(), StackFrame::INTERNAL); 1234 FrameScope frame_scope(masm(), StackFrame::INTERNAL);
1263 1235
1264 if (must_preserve_receiver_reg) { 1236 if (must_preserve_receiver_reg) {
1265 __ push(receiver); 1237 __ push(receiver());
1266 } 1238 }
1267 __ push(holder_reg); 1239 __ push(holder_reg);
1268 __ push(name_reg); 1240 __ push(this->name());
1269 1241
1270 // Invoke an interceptor. Note: map checks from receiver to 1242 // Invoke an interceptor. Note: map checks from receiver to
1271 // interceptor's holder has been compiled before (see a caller 1243 // interceptor's holder has been compiled before (see a caller
1272 // of this method.) 1244 // of this method.)
1273 CompileCallLoadPropertyWithInterceptor(masm(), 1245 CompileCallLoadPropertyWithInterceptor(masm(),
1274 receiver, 1246 receiver(),
1275 holder_reg, 1247 holder_reg,
1276 name_reg, 1248 this->name(),
1277 interceptor_holder); 1249 interceptor_holder);
1278 1250
1279 // Check if interceptor provided a value for property. If it's 1251 // Check if interceptor provided a value for property. If it's
1280 // the case, return immediately. 1252 // the case, return immediately.
1281 Label interceptor_failed; 1253 Label interceptor_failed;
1282 __ cmp(eax, factory()->no_interceptor_result_sentinel()); 1254 __ cmp(eax, factory()->no_interceptor_result_sentinel());
1283 __ j(equal, &interceptor_failed); 1255 __ j(equal, &interceptor_failed);
1284 frame_scope.GenerateLeaveFrame(); 1256 frame_scope.GenerateLeaveFrame();
1285 __ ret(0); 1257 __ ret(0);
1286 1258
1287 // Clobber registers when generating debug-code to provoke errors. 1259 // Clobber registers when generating debug-code to provoke errors.
1288 __ bind(&interceptor_failed); 1260 __ bind(&interceptor_failed);
1289 if (FLAG_debug_code) { 1261 if (FLAG_debug_code) {
1290 __ mov(receiver, Immediate(BitCast<int32_t>(kZapValue))); 1262 __ mov(receiver(), Immediate(BitCast<int32_t>(kZapValue)));
1291 __ mov(holder_reg, Immediate(BitCast<int32_t>(kZapValue))); 1263 __ mov(holder_reg, Immediate(BitCast<int32_t>(kZapValue)));
1292 __ mov(name_reg, Immediate(BitCast<int32_t>(kZapValue))); 1264 __ mov(this->name(), Immediate(BitCast<int32_t>(kZapValue)));
1293 } 1265 }
1294 1266
1295 __ pop(name_reg); 1267 __ pop(this->name());
1296 __ pop(holder_reg); 1268 __ pop(holder_reg);
1297 if (must_preserve_receiver_reg) { 1269 if (must_preserve_receiver_reg) {
1298 __ pop(receiver); 1270 __ pop(receiver());
1299 } 1271 }
1300 1272
1301 // Leave the internal frame. 1273 // Leave the internal frame.
1302 } 1274 }
1303 1275
1304 // Check that the maps from interceptor's holder to lookup's holder 1276 GenerateLoadPostInterceptor(holder_reg, interceptor_holder, name, lookup);
1305 // haven't changed. And load lookup's holder into holder_reg.
1306 if (must_perfrom_prototype_check) {
1307 holder_reg = CheckPrototypes(interceptor_holder,
1308 holder_reg,
1309 Handle<JSObject>(lookup->holder()),
1310 scratch1,
1311 scratch2,
1312 scratch3,
1313 name,
1314 miss);
1315 }
1316
1317 if (lookup->IsField()) {
1318 // We found FIELD property in prototype chain of interceptor's holder.
1319 // Retrieve a field from field's holder.
1320 GenerateFastPropertyLoad(masm(), eax, holder_reg,
1321 Handle<JSObject>(lookup->holder()),
1322 lookup->GetFieldIndex());
1323 __ ret(0);
1324 } else {
1325 // We found CALLBACKS property in prototype chain of interceptor's
1326 // holder.
1327 ASSERT(lookup->type() == CALLBACKS);
1328 Handle<AccessorInfo> callback(
1329 AccessorInfo::cast(lookup->GetCallbackObject()));
1330 ASSERT(callback->getter() != NULL);
1331
1332 // Tail call to runtime.
1333 // Important invariant in CALLBACKS case: the code above must be
1334 // structured to never clobber |receiver| register.
1335 __ pop(scratch2); // return address
1336 __ push(receiver);
1337 __ push(holder_reg);
1338 __ mov(holder_reg, Immediate(callback));
1339 __ push(FieldOperand(holder_reg, AccessorInfo::kDataOffset));
1340 __ push(Immediate(reinterpret_cast<int>(isolate())));
1341 __ push(holder_reg);
1342 __ push(name_reg);
1343 __ push(scratch2); // restore return address
1344
1345 ExternalReference ref =
1346 ExternalReference(IC_Utility(IC::kLoadCallbackProperty),
1347 masm()->isolate());
1348 __ TailCallExternalReference(ref, 6, 1);
1349 }
1350 } else { // !compile_followup_inline 1277 } else { // !compile_followup_inline
1351 // Call the runtime system to load the interceptor. 1278 // Call the runtime system to load the interceptor.
1352 // Check that the maps haven't changed. 1279 // Check that the maps haven't changed.
1353 Register holder_reg = 1280 __ pop(scratch2()); // save old return address
1354 CheckPrototypes(object, receiver, interceptor_holder, 1281 PushInterceptorArguments(masm(), receiver(), holder_reg,
1355 scratch1, scratch2, scratch3, name, miss); 1282 this->name(), interceptor_holder);
1356 __ pop(scratch2); // save old return address 1283 __ push(scratch2()); // restore old return address
1357 PushInterceptorArguments(masm(), receiver, holder_reg,
1358 name_reg, interceptor_holder);
1359 __ push(scratch2); // restore old return address
1360 1284
1361 ExternalReference ref = 1285 ExternalReference ref =
1362 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), 1286 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForLoad),
1363 isolate()); 1287 isolate());
1364 __ TailCallExternalReference(ref, 6, 1); 1288 __ TailCallExternalReference(ref, 6, 1);
1365 } 1289 }
1366 } 1290 }
1367 1291
1368 1292
1293 void BaseLoadStubCompiler::GenerateLoadPostInterceptor(
1294 Register interceptor_reg,
1295 Handle<JSObject> interceptor_holder,
1296 Handle<String> name,
1297 LookupResult* lookup) {
1298 Label success;
1299 Handle<JSObject> holder(lookup->holder());
1300 if (lookup->IsField()) {
1301 // We found FIELD property in prototype chain of interceptor's holder.
1302 // Retrieve a field from field's holder.
1303 Register reg = GenerateHandlerFrontend(interceptor_holder,
1304 interceptor_reg,
1305 holder,
1306 name,
1307 &success,
1308 Handle<AccessorInfo>::null(),
1309 false);
1310 __ bind(&success);
1311 GenerateLoadField(reg, holder, lookup->GetFieldIndex());
1312 } else {
1313 // We found CALLBACKS property in prototype chain of interceptor's
1314 // holder.
1315 ASSERT(lookup->type() == CALLBACKS);
1316 Handle<AccessorInfo> callback(
1317 AccessorInfo::cast(lookup->GetCallbackObject()));
1318 ASSERT(callback->getter() != NULL);
1319
1320 Register reg = GenerateHandlerFrontend(interceptor_holder,
1321 interceptor_reg,
1322 holder,
1323 name,
1324 &success,
1325 callback,
1326 false);
1327 __ bind(&success);
1328 GenerateLoadCallback(reg, callback);
1329 }
1330 }
1331
1332
1369 void CallStubCompiler::GenerateNameCheck(Handle<String> name, Label* miss) { 1333 void CallStubCompiler::GenerateNameCheck(Handle<String> name, Label* miss) {
1370 if (kind_ == Code::KEYED_CALL_IC) { 1334 if (kind_ == Code::KEYED_CALL_IC) {
1371 __ cmp(ecx, Immediate(name)); 1335 __ cmp(ecx, Immediate(name));
1372 __ j(not_equal, miss); 1336 __ j(not_equal, miss);
1373 } 1337 }
1374 } 1338 }
1375 1339
1376 1340
1377 void CallStubCompiler::GenerateGlobalReceiverCheck(Handle<JSObject> object, 1341 void CallStubCompiler::GenerateGlobalReceiverCheck(Handle<JSObject> object,
1378 Handle<JSObject> holder, 1342 Handle<JSObject> holder,
(...skipping 1368 matching lines...) Expand 10 before | Expand all | Expand 10 after
2747 Handle<JSObject> receiver, 2711 Handle<JSObject> receiver,
2748 Handle<JSObject> holder, 2712 Handle<JSObject> holder,
2749 Handle<JSFunction> setter) { 2713 Handle<JSFunction> setter) {
2750 // ----------- S t a t e ------------- 2714 // ----------- S t a t e -------------
2751 // -- eax : value 2715 // -- eax : value
2752 // -- ecx : name 2716 // -- ecx : name
2753 // -- edx : receiver 2717 // -- edx : receiver
2754 // -- esp[0] : return address 2718 // -- esp[0] : return address
2755 // ----------------------------------- 2719 // -----------------------------------
2756 Label miss; 2720 Label miss;
2757 2721
Toon Verwaest 2013/02/06 14:06:30 Use other register so it looks exactly the same as
2758 // Check that the maps haven't changed, preserving the name register. 2722 // Check that the maps haven't changed, preserving the name register.
2759 __ push(ecx); 2723 __ push(ecx);
2760 __ JumpIfSmi(edx, &miss); 2724 __ JumpIfSmi(edx, &miss);
2761 CheckPrototypes(receiver, edx, holder, ebx, ecx, edi, name, &miss); 2725 CheckPrototypes(receiver, edx, holder, ebx, ecx, edi, name, &miss);
2762 __ pop(ecx); 2726 __ pop(ecx);
2763 2727
2764 GenerateStoreViaSetter(masm(), setter); 2728 GenerateStoreViaSetter(masm(), setter);
2765 2729
2766 __ bind(&miss); 2730 __ bind(&miss);
2767 __ pop(ecx); 2731 __ pop(ecx);
(...skipping 1151 matching lines...) Expand 10 before | Expand all | Expand 10 after
3919 __ jmp(ic_slow, RelocInfo::CODE_TARGET); 3883 __ jmp(ic_slow, RelocInfo::CODE_TARGET);
3920 } 3884 }
3921 } 3885 }
3922 3886
3923 3887
3924 #undef __ 3888 #undef __
3925 3889
3926 } } // namespace v8::internal 3890 } } // namespace v8::internal
3927 3891
3928 #endif // V8_TARGET_ARCH_IA32 3892 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « no previous file | src/ic.h » ('j') | src/stub-cache.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698