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

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: 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 | « src/arm/stub-cache-arm.cc ('k') | src/ic.h » ('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 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::HandlerFrontendFooter(Label* success,
1048 Handle<JSObject> holder, 1048 Label* miss) {
1049 Register receiver, 1049 __ jmp(success);
1050 Register scratch1, 1050 __ bind(miss);
1051 Register scratch2, 1051 GenerateLoadMiss(masm(), kind());
1052 Register scratch3, 1052 }
1053 PropertyIndex index,
1054 Handle<String> name,
1055 Label* miss) {
1056 // Check that the receiver isn't a smi.
1057 __ JumpIfSmi(receiver, miss);
1058 1053
1059 // Check the prototype chain.
1060 Register reg = CheckPrototypes(
1061 object, receiver, holder, scratch1, scratch2, scratch3, name, miss);
1062 1054
1055 Register BaseLoadStubCompiler::CallbackHandlerFrontend(
1056 Handle<JSObject> object,
1057 Register object_reg,
1058 Handle<JSObject> holder,
1059 Handle<String> name,
1060 Label* success,
1061 FrontendCheckType check,
1062 Handle<AccessorInfo> callback) {
1063 Label miss;
1064
1065 Register reg = HandlerFrontendHeader(
1066 object, object_reg, holder, name, &miss, check);
1067
1068 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) {
1069 ASSERT(!reg.is(scratch2()));
1070 ASSERT(!reg.is(scratch3()));
1071 Register dictionary = scratch1();
1072 bool must_preserve_dictionary_reg = reg.is(dictionary);
1073
1074 // Load the properties dictionary.
1075 if (must_preserve_dictionary_reg) {
1076 __ push(dictionary);
1077 }
1078 __ mov(dictionary, FieldOperand(reg, JSObject::kPropertiesOffset));
1079
1080 // Probe the dictionary.
1081 Label probe_done, pop_and_miss;
1082 StringDictionaryLookupStub::GeneratePositiveLookup(masm(),
1083 &pop_and_miss,
1084 &probe_done,
1085 dictionary,
1086 this->name(),
1087 scratch2(),
1088 scratch3());
1089 __ bind(&pop_and_miss);
1090 if (must_preserve_dictionary_reg) {
1091 __ pop(dictionary);
1092 }
1093 __ jmp(&miss);
1094 __ bind(&probe_done);
1095
1096 // If probing finds an entry in the dictionary, scratch2 contains the
1097 // index into the dictionary. Check that the value is the callback.
1098 Register index = scratch2();
1099 const int kElementsStartOffset =
1100 StringDictionary::kHeaderSize +
1101 StringDictionary::kElementsStartIndex * kPointerSize;
1102 const int kValueOffset = kElementsStartOffset + kPointerSize;
1103 __ mov(scratch3(),
1104 Operand(dictionary, index, times_4, kValueOffset - kHeapObjectTag));
1105 if (must_preserve_dictionary_reg) {
1106 __ pop(dictionary);
1107 }
1108 __ cmp(scratch3(), callback);
1109 __ j(not_equal, &miss);
1110 }
1111
1112 HandlerFrontendFooter(success, &miss);
1113 return reg;
1114 }
1115
1116
1117 void BaseLoadStubCompiler::NonexistentHandlerFrontend(
1118 Handle<JSObject> object,
1119 Handle<JSObject> last,
1120 Handle<String> name,
1121 Label* success,
1122 Handle<GlobalObject> global) {
1123 Label miss;
1124
1125 Register reg = HandlerFrontendHeader(
1126 object, receiver(), last, name, &miss, PERFORM_INITIAL_CHECKS);
1127
1128 // If the last object in the prototype chain is a global object,
1129 // check that the global property cell is empty.
1130 if (!global.is_null()) {
1131 GenerateCheckPropertyCell(masm(), global, name, scratch2(), &miss);
1132 }
1133
1134 if (!last->HasFastProperties()) {
1135 __ mov(scratch2(), FieldOperand(reg, HeapObject::kMapOffset));
1136 __ mov(scratch2(), FieldOperand(scratch2(), Map::kPrototypeOffset));
1137 __ cmp(scratch2(), isolate()->factory()->null_value());
1138 __ j(not_equal, &miss);
1139 }
1140
1141 HandlerFrontendFooter(success, &miss);
1142 }
1143
1144
1145 void BaseLoadStubCompiler::GenerateLoadField(Register reg,
1146 Handle<JSObject> holder,
1147 PropertyIndex index) {
1063 // Get the value from the properties. 1148 // Get the value from the properties.
1064 GenerateFastPropertyLoad(masm(), eax, reg, holder, index); 1149 GenerateFastPropertyLoad(masm(), eax, reg, holder, index);
1065 __ ret(0); 1150 __ ret(0);
1066 } 1151 }
1067 1152
1068 1153
1069 void StubCompiler::GenerateDictionaryLoadCallback(Register receiver, 1154 void BaseLoadStubCompiler::GenerateLoadCallback(Register reg,
1070 Register name_reg, 1155 Handle<AccessorInfo> callback) {
1071 Register scratch1, 1156 // Insert additional parameters into the stack frame above return address.
1072 Register scratch2, 1157 ASSERT(!scratch3().is(reg));
1073 Register scratch3, 1158 __ pop(scratch3()); // Get return address to place it below.
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 1159
1082 // Load the properties dictionary. 1160 __ push(receiver()); // receiver
1083 if (must_preserve_dictionary_reg) { 1161 __ mov(scratch2(), esp);
1084 __ push(dictionary); 1162 ASSERT(!scratch2().is(reg));
1085 }
1086 __ mov(dictionary, FieldOperand(receiver, JSObject::kPropertiesOffset));
1087
1088 // Probe the dictionary.
1089 Label probe_done, pop_and_miss;
1090 StringDictionaryLookupStub::GeneratePositiveLookup(masm(),
1091 &pop_and_miss,
1092 &probe_done,
1093 dictionary,
1094 name_reg,
1095 scratch2,
1096 scratch3);
1097 __ bind(&pop_and_miss);
1098 if (must_preserve_dictionary_reg) {
1099 __ pop(dictionary);
1100 }
1101 __ jmp(miss);
1102 __ bind(&probe_done);
1103
1104 // If probing finds an entry in the dictionary, scratch2 contains the
1105 // index into the dictionary. Check that the value is the callback.
1106 Register index = scratch2;
1107 const int kElementsStartOffset =
1108 StringDictionary::kHeaderSize +
1109 StringDictionary::kElementsStartIndex * kPointerSize;
1110 const int kValueOffset = kElementsStartOffset + kPointerSize;
1111 __ mov(scratch3,
1112 Operand(dictionary, index, times_4, kValueOffset - kHeapObjectTag));
1113 if (must_preserve_dictionary_reg) {
1114 __ pop(dictionary);
1115 }
1116 __ cmp(scratch3, callback);
1117 __ j(not_equal, miss);
1118 }
1119
1120
1121 void StubCompiler::GenerateLoadCallback(Handle<JSObject> object,
1122 Handle<JSObject> holder,
1123 Register receiver,
1124 Register name_reg,
1125 Register scratch1,
1126 Register scratch2,
1127 Register scratch3,
1128 Register scratch4,
1129 Handle<AccessorInfo> callback,
1130 Handle<String> name,
1131 Label* miss) {
1132 // Check that the receiver isn't a smi.
1133 __ JumpIfSmi(receiver, miss);
1134
1135 // Check that the maps haven't changed.
1136 Register reg = CheckPrototypes(object, receiver, holder, scratch1,
1137 scratch2, scratch3, name, miss);
1138
1139 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) {
1140 GenerateDictionaryLoadCallback(
1141 reg, name_reg, scratch1, scratch2, scratch3, callback, name, miss);
1142 }
1143
1144 // Insert additional parameters into the stack frame above return address.
1145 ASSERT(!scratch3.is(reg));
1146 __ pop(scratch3); // Get return address to place it below.
1147
1148 __ push(receiver); // receiver
1149 __ mov(scratch2, esp);
1150 ASSERT(!scratch2.is(reg));
1151 __ push(reg); // holder 1163 __ push(reg); // holder
1152 // Push data from AccessorInfo. 1164 // Push data from AccessorInfo.
1153 if (isolate()->heap()->InNewSpace(callback->data())) { 1165 if (isolate()->heap()->InNewSpace(callback->data())) {
1154 __ mov(scratch1, Immediate(callback)); 1166 __ mov(scratch1(), Immediate(callback));
1155 __ push(FieldOperand(scratch1, AccessorInfo::kDataOffset)); 1167 __ push(FieldOperand(scratch1(), AccessorInfo::kDataOffset));
1156 } else { 1168 } else {
1157 __ push(Immediate(Handle<Object>(callback->data()))); 1169 __ push(Immediate(Handle<Object>(callback->data())));
1158 } 1170 }
1159 __ push(Immediate(reinterpret_cast<int>(isolate()))); 1171 __ push(Immediate(reinterpret_cast<int>(isolate())));
1160 1172
1161 // Save a pointer to where we pushed the arguments pointer. 1173 // Save a pointer to where we pushed the arguments pointer.
1162 // This will be passed as the const AccessorInfo& to the C++ callback. 1174 // This will be passed as the const AccessorInfo& to the C++ callback.
1163 __ push(scratch2); 1175 __ push(scratch2());
1164 1176
1165 __ push(name_reg); // name 1177 __ push(name()); // name
1166 __ mov(ebx, esp); // esp points to reference to name (handler). 1178 __ mov(ebx, esp); // esp points to reference to name (handler).
1167 1179
1168 __ push(scratch3); // Restore return address. 1180 __ push(scratch3()); // Restore return address.
1169 1181
1170 // 4 elements array for v8::Arguments::values_, handler for name and pointer 1182 // 4 elements array for v8::Arguments::values_, handler for name and pointer
1171 // to the values (it considered as smi in GC). 1183 // to the values (it considered as smi in GC).
1172 const int kStackSpace = 6; 1184 const int kStackSpace = 6;
1173 const int kApiArgc = 2; 1185 const int kApiArgc = 2;
1174 1186
1175 __ PrepareCallApiFunction(kApiArgc); 1187 __ PrepareCallApiFunction(kApiArgc);
1176 __ mov(ApiParameterOperand(0), ebx); // name. 1188 __ mov(ApiParameterOperand(0), ebx); // name.
1177 __ add(ebx, Immediate(kPointerSize)); 1189 __ add(ebx, Immediate(kPointerSize));
1178 __ mov(ApiParameterOperand(1), ebx); // arguments pointer. 1190 __ mov(ApiParameterOperand(1), ebx); // arguments pointer.
1179 1191
1180 // Emitting a stub call may try to allocate (if the code is not 1192 // Emitting a stub call may try to allocate (if the code is not
1181 // already generated). Do not allow the assembler to perform a 1193 // already generated). Do not allow the assembler to perform a
1182 // garbage collection but instead return the allocation failure 1194 // garbage collection but instead return the allocation failure
1183 // object. 1195 // object.
1184 Address getter_address = v8::ToCData<Address>(callback->getter()); 1196 Address getter_address = v8::ToCData<Address>(callback->getter());
1185 __ CallApiFunctionAndReturn(getter_address, kStackSpace); 1197 __ CallApiFunctionAndReturn(getter_address, kStackSpace);
1186 } 1198 }
1187 1199
1188 1200
1189 void StubCompiler::GenerateLoadConstant(Handle<JSObject> object, 1201 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. 1202 // Return the constant value.
1206 __ LoadHeapObject(eax, value); 1203 __ LoadHeapObject(eax, value);
1207 __ ret(0); 1204 __ ret(0);
1208 } 1205 }
1209 1206
1210 1207
1211 void StubCompiler::GenerateLoadInterceptor(Handle<JSObject> object, 1208 void BaseLoadStubCompiler::GenerateLoadInterceptor(
1212 Handle<JSObject> interceptor_holder, 1209 Register holder_reg,
1213 LookupResult* lookup, 1210 Handle<JSObject> object,
1214 Register receiver, 1211 Handle<JSObject> interceptor_holder,
1215 Register name_reg, 1212 LookupResult* lookup,
1216 Register scratch1, 1213 Handle<String> name) {
1217 Register scratch2,
1218 Register scratch3,
1219 Handle<String> name,
1220 Label* miss) {
1221 ASSERT(interceptor_holder->HasNamedInterceptor()); 1214 ASSERT(interceptor_holder->HasNamedInterceptor());
1222 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); 1215 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined());
1223 1216
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 1217 // So far the most popular follow ups for interceptor loads are FIELD
1228 // and CALLBACKS, so inline only them, other cases may be added 1218 // and CALLBACKS, so inline only them, other cases may be added
1229 // later. 1219 // later.
1230 bool compile_followup_inline = false; 1220 bool compile_followup_inline = false;
1231 if (lookup->IsFound() && lookup->IsCacheable()) { 1221 if (lookup->IsFound() && lookup->IsCacheable()) {
1232 if (lookup->IsField()) { 1222 if (lookup->IsField()) {
1233 compile_followup_inline = true; 1223 compile_followup_inline = true;
1234 } else if (lookup->type() == CALLBACKS && 1224 } else if (lookup->type() == CALLBACKS &&
1235 lookup->GetCallbackObject()->IsAccessorInfo()) { 1225 lookup->GetCallbackObject()->IsAccessorInfo()) {
1236 AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject()); 1226 AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject());
1237 compile_followup_inline = callback->getter() != NULL && 1227 compile_followup_inline = callback->getter() != NULL &&
1238 callback->IsCompatibleReceiver(*object); 1228 callback->IsCompatibleReceiver(*object);
1239 } 1229 }
1240 } 1230 }
1241 1231
1242 if (compile_followup_inline) { 1232 if (compile_followup_inline) {
1243 // Compile the interceptor call, followed by inline code to load the 1233 // Compile the interceptor call, followed by inline code to load the
1244 // property from further up the prototype chain if the call fails. 1234 // property from further up the prototype chain if the call fails.
1245 // Check that the maps haven't changed. 1235 // Check that the maps haven't changed.
1246 Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder, 1236 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 1237
1251 // Preserve the receiver register explicitly whenever it is different from 1238 // Preserve the receiver register explicitly whenever it is different from
1252 // the holder and it is needed should the interceptor return without any 1239 // 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, 1240 // 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. 1241 // the FIELD case might cause a miss during the prototype check.
1255 bool must_perfrom_prototype_check = *interceptor_holder != lookup->holder(); 1242 bool must_perfrom_prototype_check = *interceptor_holder != lookup->holder();
1256 bool must_preserve_receiver_reg = !receiver.is(holder_reg) && 1243 bool must_preserve_receiver_reg = !receiver().is(holder_reg) &&
1257 (lookup->type() == CALLBACKS || must_perfrom_prototype_check); 1244 (lookup->type() == CALLBACKS || must_perfrom_prototype_check);
1258 1245
1259 // Save necessary data before invoking an interceptor. 1246 // Save necessary data before invoking an interceptor.
1260 // Requires a frame to make GC aware of pushed pointers. 1247 // Requires a frame to make GC aware of pushed pointers.
1261 { 1248 {
1262 FrameScope frame_scope(masm(), StackFrame::INTERNAL); 1249 FrameScope frame_scope(masm(), StackFrame::INTERNAL);
1263 1250
1264 if (must_preserve_receiver_reg) { 1251 if (must_preserve_receiver_reg) {
1265 __ push(receiver); 1252 __ push(receiver());
1266 } 1253 }
1267 __ push(holder_reg); 1254 __ push(holder_reg);
1268 __ push(name_reg); 1255 __ push(this->name());
1269 1256
1270 // Invoke an interceptor. Note: map checks from receiver to 1257 // Invoke an interceptor. Note: map checks from receiver to
1271 // interceptor's holder has been compiled before (see a caller 1258 // interceptor's holder has been compiled before (see a caller
1272 // of this method.) 1259 // of this method.)
1273 CompileCallLoadPropertyWithInterceptor(masm(), 1260 CompileCallLoadPropertyWithInterceptor(masm(),
1274 receiver, 1261 receiver(),
1275 holder_reg, 1262 holder_reg,
1276 name_reg, 1263 this->name(),
1277 interceptor_holder); 1264 interceptor_holder);
1278 1265
1279 // Check if interceptor provided a value for property. If it's 1266 // Check if interceptor provided a value for property. If it's
1280 // the case, return immediately. 1267 // the case, return immediately.
1281 Label interceptor_failed; 1268 Label interceptor_failed;
1282 __ cmp(eax, factory()->no_interceptor_result_sentinel()); 1269 __ cmp(eax, factory()->no_interceptor_result_sentinel());
1283 __ j(equal, &interceptor_failed); 1270 __ j(equal, &interceptor_failed);
1284 frame_scope.GenerateLeaveFrame(); 1271 frame_scope.GenerateLeaveFrame();
1285 __ ret(0); 1272 __ ret(0);
1286 1273
1287 // Clobber registers when generating debug-code to provoke errors. 1274 // Clobber registers when generating debug-code to provoke errors.
1288 __ bind(&interceptor_failed); 1275 __ bind(&interceptor_failed);
1289 if (FLAG_debug_code) { 1276 if (FLAG_debug_code) {
1290 __ mov(receiver, Immediate(BitCast<int32_t>(kZapValue))); 1277 __ mov(receiver(), Immediate(BitCast<int32_t>(kZapValue)));
1291 __ mov(holder_reg, Immediate(BitCast<int32_t>(kZapValue))); 1278 __ mov(holder_reg, Immediate(BitCast<int32_t>(kZapValue)));
1292 __ mov(name_reg, Immediate(BitCast<int32_t>(kZapValue))); 1279 __ mov(this->name(), Immediate(BitCast<int32_t>(kZapValue)));
1293 } 1280 }
1294 1281
1295 __ pop(name_reg); 1282 __ pop(this->name());
1296 __ pop(holder_reg); 1283 __ pop(holder_reg);
1297 if (must_preserve_receiver_reg) { 1284 if (must_preserve_receiver_reg) {
1298 __ pop(receiver); 1285 __ pop(receiver());
1299 } 1286 }
1300 1287
1301 // Leave the internal frame. 1288 // Leave the internal frame.
1302 } 1289 }
1303 1290
1304 // Check that the maps from interceptor's holder to lookup's holder 1291 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 1292 } else { // !compile_followup_inline
1351 // Call the runtime system to load the interceptor. 1293 // Call the runtime system to load the interceptor.
1352 // Check that the maps haven't changed. 1294 // Check that the maps haven't changed.
1353 Register holder_reg = 1295 __ pop(scratch2()); // save old return address
1354 CheckPrototypes(object, receiver, interceptor_holder, 1296 PushInterceptorArguments(masm(), receiver(), holder_reg,
1355 scratch1, scratch2, scratch3, name, miss); 1297 this->name(), interceptor_holder);
1356 __ pop(scratch2); // save old return address 1298 __ 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 1299
1361 ExternalReference ref = 1300 ExternalReference ref =
1362 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), 1301 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForLoad),
1363 isolate()); 1302 isolate());
1364 __ TailCallExternalReference(ref, 6, 1); 1303 __ TailCallExternalReference(ref, 6, 1);
1365 } 1304 }
1366 } 1305 }
1367 1306
1368 1307
1369 void CallStubCompiler::GenerateNameCheck(Handle<String> name, Label* miss) { 1308 void CallStubCompiler::GenerateNameCheck(Handle<String> name, Label* miss) {
(...skipping 1594 matching lines...) Expand 10 before | Expand all | Expand 10 after
2964 // Return the generated code. 2903 // Return the generated code.
2965 return GetCode(Code::NORMAL, factory()->empty_string(), POLYMORPHIC); 2904 return GetCode(Code::NORMAL, factory()->empty_string(), POLYMORPHIC);
2966 } 2905 }
2967 2906
2968 2907
2969 Handle<Code> LoadStubCompiler::CompileLoadNonexistent( 2908 Handle<Code> LoadStubCompiler::CompileLoadNonexistent(
2970 Handle<JSObject> object, 2909 Handle<JSObject> object,
2971 Handle<JSObject> last, 2910 Handle<JSObject> last,
2972 Handle<String> name, 2911 Handle<String> name,
2973 Handle<GlobalObject> global) { 2912 Handle<GlobalObject> global) {
2974 // ----------- S t a t e ------------- 2913 Label success;
2975 // -- ecx : name
2976 // -- edx : receiver
2977 // -- esp[0] : return address
2978 // -----------------------------------
2979 Label miss;
2980 2914
2981 // Check that the receiver isn't a smi. 2915 NonexistentHandlerFrontend(object, last, name, &success, global);
2982 __ JumpIfSmi(edx, &miss);
2983 2916
2984 Register scratch = eax; 2917 __ bind(&success);
2985
2986 // Check the maps of the full prototype chain. Also check that
2987 // global property cells up to (but not including) the last object
2988 // in the prototype chain are empty.
2989 Register result =
2990 CheckPrototypes(object, edx, last, ebx, scratch, edi, name, &miss);
2991
2992 // If the last object in the prototype chain is a global object,
2993 // check that the global property cell is empty.
2994 if (!global.is_null()) {
2995 GenerateCheckPropertyCell(masm(), global, name, scratch, &miss);
2996 }
2997
2998 if (!last->HasFastProperties()) {
2999 __ mov(scratch, FieldOperand(result, HeapObject::kMapOffset));
3000 __ mov(scratch, FieldOperand(scratch, Map::kPrototypeOffset));
3001 __ cmp(scratch, isolate()->factory()->null_value());
3002 __ j(not_equal, &miss);
3003 }
3004
3005 // Return undefined if maps of the full prototype chain are still the 2918 // Return undefined if maps of the full prototype chain are still the
3006 // same and no global property with this name contains a value. 2919 // same and no global property with this name contains a value.
3007 __ mov(eax, isolate()->factory()->undefined_value()); 2920 __ mov(eax, isolate()->factory()->undefined_value());
3008 __ ret(0); 2921 __ ret(0);
3009 2922
3010 __ bind(&miss);
3011 GenerateLoadMiss(masm(), Code::LOAD_IC);
3012
3013 // Return the generated code. 2923 // Return the generated code.
3014 return GetCode(Code::NONEXISTENT, factory()->empty_string()); 2924 return GetCode(Code::NONEXISTENT, factory()->empty_string());
3015 } 2925 }
3016 2926
3017 2927
3018 Register* LoadStubCompiler::registers() { 2928 Register* LoadStubCompiler::registers() {
3019 // receiver, name, scratch1, scratch2, scratch3, scratch4. 2929 // receiver, name, scratch1, scratch2, scratch3, scratch4.
3020 static Register registers[] = { edx, ecx, ebx, eax, edi, no_reg }; 2930 static Register registers[] = { edx, ecx, ebx, eax, edi, no_reg };
3021 return registers; 2931 return registers;
3022 } 2932 }
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
3067 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 2977 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
3068 } 2978 }
3069 __ ret(0); 2979 __ ret(0);
3070 } 2980 }
3071 2981
3072 2982
3073 #undef __ 2983 #undef __
3074 #define __ ACCESS_MASM(masm()) 2984 #define __ ACCESS_MASM(masm())
3075 2985
3076 2986
3077 Handle<Code> LoadStubCompiler::CompileLoadViaGetter(
3078 Handle<JSObject> receiver,
3079 Handle<JSObject> holder,
3080 Handle<String> name,
3081 Handle<JSFunction> getter) {
3082 // ----------- S t a t e -------------
3083 // -- ecx : name
3084 // -- edx : receiver
3085 // -- esp[0] : return address
3086 // -----------------------------------
3087 Label miss;
3088
3089 // Check that the maps haven't changed.
3090 __ JumpIfSmi(edx, &miss);
3091 CheckPrototypes(receiver, edx, holder, ebx, eax, edi, name, &miss);
3092
3093 GenerateLoadViaGetter(masm(), getter);
3094
3095 __ bind(&miss);
3096 GenerateLoadMiss(masm(), Code::LOAD_IC);
3097
3098 // Return the generated code.
3099 return GetCode(Code::CALLBACKS, name);
3100 }
3101
3102
3103 Handle<Code> LoadStubCompiler::CompileLoadGlobal( 2987 Handle<Code> LoadStubCompiler::CompileLoadGlobal(
3104 Handle<JSObject> object, 2988 Handle<JSObject> object,
3105 Handle<GlobalObject> holder, 2989 Handle<GlobalObject> global,
3106 Handle<JSGlobalPropertyCell> cell, 2990 Handle<JSGlobalPropertyCell> cell,
3107 Handle<String> name, 2991 Handle<String> name,
3108 bool is_dont_delete) { 2992 bool is_dont_delete) {
3109 // ----------- S t a t e ------------- 2993 Label success, miss;
3110 // -- ecx : name
3111 // -- edx : receiver
3112 // -- esp[0] : return address
3113 // -----------------------------------
3114 Label miss;
3115 2994
3116 // Check that the maps haven't changed. 2995 HandlerFrontendHeader(object, receiver(), Handle<JSObject>::cast(global),
3117 __ JumpIfSmi(edx, &miss); 2996 name, &miss, PERFORM_INITIAL_CHECKS);
3118 CheckPrototypes(object, edx, holder, ebx, eax, edi, name, &miss);
3119
3120 // Get the value from the cell. 2997 // Get the value from the cell.
3121 if (Serializer::enabled()) { 2998 if (Serializer::enabled()) {
3122 __ mov(ebx, Immediate(cell)); 2999 __ mov(eax, Immediate(cell));
3123 __ mov(ebx, FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset)); 3000 __ mov(eax, FieldOperand(eax, JSGlobalPropertyCell::kValueOffset));
3124 } else { 3001 } else {
3125 __ mov(ebx, Operand::Cell(cell)); 3002 __ mov(eax, Operand::Cell(cell));
3126 } 3003 }
3127 3004
3128 // Check for deleted property if property can actually be deleted. 3005 // Check for deleted property if property can actually be deleted.
3129 if (!is_dont_delete) { 3006 if (!is_dont_delete) {
3130 __ cmp(ebx, factory()->the_hole_value()); 3007 __ cmp(eax, factory()->the_hole_value());
3131 __ j(equal, &miss); 3008 __ j(equal, &miss);
3132 } else if (FLAG_debug_code) { 3009 } else if (FLAG_debug_code) {
3133 __ cmp(ebx, factory()->the_hole_value()); 3010 __ cmp(eax, factory()->the_hole_value());
3134 __ Check(not_equal, "DontDelete cells can't contain the hole"); 3011 __ Check(not_equal, "DontDelete cells can't contain the hole");
3135 } 3012 }
3136 3013
3014 HandlerFrontendFooter(&success, &miss);
3015 __ bind(&success);
3016
3137 Counters* counters = isolate()->counters(); 3017 Counters* counters = isolate()->counters();
3138 __ IncrementCounter(counters->named_load_global_stub(), 1); 3018 __ IncrementCounter(counters->named_load_global_stub(), 1);
3139 __ mov(eax, ebx); 3019 // The code above already loads the result into the return register.
3140 __ ret(0); 3020 __ ret(0);
3141 3021
3142 __ bind(&miss);
3143 __ IncrementCounter(counters->named_load_global_stub_miss(), 1);
3144 GenerateLoadMiss(masm(), Code::LOAD_IC);
3145
3146 // Return the generated code. 3022 // Return the generated code.
3147 return GetCode(Code::NORMAL, name); 3023 return GetCode(Code::NORMAL, name);
3148 } 3024 }
3149 3025
3150 3026
3151 Handle<Code> KeyedLoadStubCompiler::CompileLoadElement( 3027 Handle<Code> KeyedLoadStubCompiler::CompileLoadElement(
3152 Handle<Map> receiver_map) { 3028 Handle<Map> receiver_map) {
3153 // ----------- S t a t e ------------- 3029 // ----------- S t a t e -------------
3154 // -- ecx : key 3030 // -- ecx : key
3155 // -- edx : receiver 3031 // -- edx : receiver
(...skipping 763 matching lines...) Expand 10 before | Expand all | Expand 10 after
3919 __ jmp(ic_slow, RelocInfo::CODE_TARGET); 3795 __ jmp(ic_slow, RelocInfo::CODE_TARGET);
3920 } 3796 }
3921 } 3797 }
3922 3798
3923 3799
3924 #undef __ 3800 #undef __
3925 3801
3926 } } // namespace v8::internal 3802 } } // namespace v8::internal
3927 3803
3928 #endif // V8_TARGET_ARCH_IA32 3804 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/arm/stub-cache-arm.cc ('k') | src/ic.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698