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

Side by Side Diff: src/x64/stub-cache-x64.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/stub-cache.cc ('k') | test/cctest/test-serialize.cc » ('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 1003 matching lines...) Expand 10 before | Expand all | Expand 10 after
1014 // If we've skipped any global objects, it's not enough to verify that 1014 // If we've skipped any global objects, it's not enough to verify that
1015 // their maps haven't changed. We also need to check that the property 1015 // their maps haven't changed. We also need to check that the property
1016 // cell for the property is still empty. 1016 // cell for the property is still empty.
1017 GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss); 1017 GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss);
1018 1018
1019 // Return the register containing the holder. 1019 // Return the register containing the holder.
1020 return reg; 1020 return reg;
1021 } 1021 }
1022 1022
1023 1023
1024 void StubCompiler::GenerateLoadField(Handle<JSObject> object, 1024 void BaseLoadStubCompiler::HandlerFrontendFooter(Label* success,
1025 Handle<JSObject> holder, 1025 Label* miss) {
1026 Register receiver, 1026 __ jmp(success);
1027 Register scratch1, 1027 __ bind(miss);
1028 Register scratch2, 1028 GenerateLoadMiss(masm(), kind());
1029 Register scratch3, 1029 }
1030 PropertyIndex index,
1031 Handle<String> name,
1032 Label* miss) {
1033 // Check that the receiver isn't a smi.
1034 __ JumpIfSmi(receiver, miss);
1035 1030
1036 // Check the prototype chain.
1037 Register reg = CheckPrototypes(
1038 object, receiver, holder, scratch1, scratch2, scratch3, name, miss);
1039 1031
1032 Register BaseLoadStubCompiler::CallbackHandlerFrontend(
1033 Handle<JSObject> object,
1034 Register object_reg,
1035 Handle<JSObject> holder,
1036 Handle<String> name,
1037 Label* success,
1038 FrontendCheckType check,
1039 Handle<AccessorInfo> callback) {
1040 Label miss;
1041
1042 Register reg = HandlerFrontendHeader(
1043 object, object_reg, holder, name, &miss, check);
1044
1045 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) {
1046 ASSERT(!reg.is(scratch2()));
1047 ASSERT(!reg.is(scratch3()));
1048 ASSERT(!reg.is(scratch4()));
1049
1050 // Load the properties dictionary.
1051 Register dictionary = scratch4();
1052 __ movq(dictionary, FieldOperand(reg, JSObject::kPropertiesOffset));
1053
1054 // Probe the dictionary.
1055 Label probe_done;
1056 StringDictionaryLookupStub::GeneratePositiveLookup(masm(),
1057 &miss,
1058 &probe_done,
1059 dictionary,
1060 this->name(),
1061 scratch2(),
1062 scratch3());
1063 __ bind(&probe_done);
1064
1065 // If probing finds an entry in the dictionary, scratch3 contains the
1066 // index into the dictionary. Check that the value is the callback.
1067 Register index = scratch3();
1068 const int kElementsStartOffset =
1069 StringDictionary::kHeaderSize +
1070 StringDictionary::kElementsStartIndex * kPointerSize;
1071 const int kValueOffset = kElementsStartOffset + kPointerSize;
1072 __ movq(scratch2(),
1073 Operand(dictionary, index, times_pointer_size,
1074 kValueOffset - kHeapObjectTag));
1075 __ movq(scratch3(), callback, RelocInfo::EMBEDDED_OBJECT);
1076 __ cmpq(scratch2(), scratch3());
1077 __ j(not_equal, &miss);
1078 }
1079
1080 HandlerFrontendFooter(success, &miss);
1081 return reg;
1082 }
1083
1084
1085 void BaseLoadStubCompiler::NonexistentHandlerFrontend(
1086 Handle<JSObject> object,
1087 Handle<JSObject> last,
1088 Handle<String> name,
1089 Label* success,
1090 Handle<GlobalObject> global) {
1091 Label miss;
1092
1093 Register reg = HandlerFrontendHeader(
1094 object, receiver(), last, name, &miss, PERFORM_INITIAL_CHECKS);
1095
1096 // If the last object in the prototype chain is a global object,
1097 // check that the global property cell is empty.
1098 if (!global.is_null()) {
1099 GenerateCheckPropertyCell(masm(), global, name, scratch2(), &miss);
1100 }
1101
1102 if (!last->HasFastProperties()) {
1103 __ movq(scratch2(), FieldOperand(reg, HeapObject::kMapOffset));
1104 __ movq(scratch2(), FieldOperand(scratch2(), Map::kPrototypeOffset));
1105 __ Cmp(scratch2(), isolate()->factory()->null_value());
1106 __ j(not_equal, &miss);
1107 }
1108
1109 HandlerFrontendFooter(success, &miss);
1110 }
1111
1112
1113 void BaseLoadStubCompiler::GenerateLoadField(Register reg,
1114 Handle<JSObject> holder,
1115 PropertyIndex index) {
1040 // Get the value from the properties. 1116 // Get the value from the properties.
1041 GenerateFastPropertyLoad(masm(), rax, reg, holder, index); 1117 GenerateFastPropertyLoad(masm(), rax, reg, holder, index);
1042 __ ret(0); 1118 __ ret(0);
1043 } 1119 }
1044 1120
1045 1121
1046 void StubCompiler::GenerateDictionaryLoadCallback(Register receiver, 1122 void BaseLoadStubCompiler::GenerateLoadCallback(Register reg,
1047 Register name_reg, 1123 Handle<AccessorInfo> callback) {
1048 Register scratch1, 1124 // Insert additional parameters into the stack frame above return address.
1049 Register scratch2, 1125 ASSERT(!scratch2().is(reg));
1050 Register scratch3, 1126 __ pop(scratch2()); // Get return address to place it below.
1051 Handle<AccessorInfo> callback,
1052 Handle<String> name,
1053 Label* miss) {
1054 ASSERT(!receiver.is(scratch1));
1055 ASSERT(!receiver.is(scratch2));
1056 ASSERT(!receiver.is(scratch3));
1057 1127
1058 // Load the properties dictionary. 1128 __ push(receiver()); // receiver
1059 Register dictionary = scratch1;
1060 __ movq(dictionary, FieldOperand(receiver, JSObject::kPropertiesOffset));
1061
1062 // Probe the dictionary.
1063 Label probe_done;
1064 StringDictionaryLookupStub::GeneratePositiveLookup(masm(),
1065 miss,
1066 &probe_done,
1067 dictionary,
1068 name_reg,
1069 scratch2,
1070 scratch3);
1071 __ bind(&probe_done);
1072
1073 // If probing finds an entry in the dictionary, scratch3 contains the
1074 // index into the dictionary. Check that the value is the callback.
1075 Register index = scratch3;
1076 const int kElementsStartOffset =
1077 StringDictionary::kHeaderSize +
1078 StringDictionary::kElementsStartIndex * kPointerSize;
1079 const int kValueOffset = kElementsStartOffset + kPointerSize;
1080 __ movq(scratch2,
1081 Operand(dictionary, index, times_pointer_size,
1082 kValueOffset - kHeapObjectTag));
1083 __ movq(scratch3, callback, RelocInfo::EMBEDDED_OBJECT);
1084 __ cmpq(scratch2, scratch3);
1085 __ j(not_equal, miss);
1086 }
1087
1088
1089 void StubCompiler::GenerateLoadCallback(Handle<JSObject> object,
1090 Handle<JSObject> holder,
1091 Register receiver,
1092 Register name_reg,
1093 Register scratch1,
1094 Register scratch2,
1095 Register scratch3,
1096 Register scratch4,
1097 Handle<AccessorInfo> callback,
1098 Handle<String> name,
1099 Label* miss) {
1100 // Check that the receiver isn't a smi.
1101 __ JumpIfSmi(receiver, miss);
1102
1103 // Check that the maps haven't changed.
1104 Register reg = CheckPrototypes(object, receiver, holder, scratch1,
1105 scratch2, scratch3, name, miss);
1106
1107 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) {
1108 GenerateDictionaryLoadCallback(
1109 reg, name_reg, scratch2, scratch3, scratch4, callback, name, miss);
1110 }
1111
1112 // Insert additional parameters into the stack frame above return address.
1113 ASSERT(!scratch2.is(reg));
1114 __ pop(scratch2); // Get return address to place it below.
1115
1116 __ push(receiver); // receiver
1117 __ push(reg); // holder 1129 __ push(reg); // holder
1118 if (heap()->InNewSpace(callback->data())) { 1130 if (heap()->InNewSpace(callback->data())) {
1119 __ Move(scratch1, callback); 1131 __ Move(scratch1(), callback);
1120 __ push(FieldOperand(scratch1, AccessorInfo::kDataOffset)); // data 1132 __ push(FieldOperand(scratch1(), AccessorInfo::kDataOffset)); // data
1121 } else { 1133 } else {
1122 __ Push(Handle<Object>(callback->data())); 1134 __ Push(Handle<Object>(callback->data()));
1123 } 1135 }
1124 __ PushAddress(ExternalReference::isolate_address()); // isolate 1136 __ PushAddress(ExternalReference::isolate_address()); // isolate
1125 __ push(name_reg); // name 1137 __ push(name()); // name
1126 // Save a pointer to where we pushed the arguments pointer. 1138 // Save a pointer to where we pushed the arguments pointer.
1127 // This will be passed as the const AccessorInfo& to the C++ callback. 1139 // This will be passed as the const AccessorInfo& to the C++ callback.
1128 1140
1129 #if defined(__MINGW64__) 1141 #if defined(__MINGW64__)
1130 Register accessor_info_arg = rdx; 1142 Register accessor_info_arg = rdx;
1131 Register name_arg = rcx; 1143 Register name_arg = rcx;
1132 #elif defined(_WIN64) 1144 #elif defined(_WIN64)
1133 // Win64 uses first register--rcx--for returned value. 1145 // Win64 uses first register--rcx--for returned value.
1134 Register accessor_info_arg = r8; 1146 Register accessor_info_arg = r8;
1135 Register name_arg = rdx; 1147 Register name_arg = rdx;
1136 #else 1148 #else
1137 Register accessor_info_arg = rsi; 1149 Register accessor_info_arg = rsi;
1138 Register name_arg = rdi; 1150 Register name_arg = rdi;
1139 #endif 1151 #endif
1140 1152
1141 ASSERT(!name_arg.is(scratch2)); 1153 ASSERT(!name_arg.is(scratch2()));
1142 __ movq(name_arg, rsp); 1154 __ movq(name_arg, rsp);
1143 __ push(scratch2); // Restore return address. 1155 __ push(scratch2()); // Restore return address.
1144 1156
1145 // 4 elements array for v8::Arguments::values_ and handler for name. 1157 // 4 elements array for v8::Arguments::values_ and handler for name.
1146 const int kStackSpace = 5; 1158 const int kStackSpace = 5;
1147 1159
1148 // Allocate v8::AccessorInfo in non-GCed stack space. 1160 // Allocate v8::AccessorInfo in non-GCed stack space.
1149 const int kArgStackSpace = 1; 1161 const int kArgStackSpace = 1;
1150 1162
1151 __ PrepareCallApiFunction(kArgStackSpace); 1163 __ PrepareCallApiFunction(kArgStackSpace);
1152 __ lea(rax, Operand(name_arg, 4 * kPointerSize)); 1164 __ lea(rax, Operand(name_arg, 4 * kPointerSize));
1153 1165
1154 // v8::AccessorInfo::args_. 1166 // v8::AccessorInfo::args_.
1155 __ movq(StackSpaceOperand(0), rax); 1167 __ movq(StackSpaceOperand(0), rax);
1156 1168
1157 // The context register (rsi) has been saved in PrepareCallApiFunction and 1169 // The context register (rsi) has been saved in PrepareCallApiFunction and
1158 // could be used to pass arguments. 1170 // could be used to pass arguments.
1159 __ lea(accessor_info_arg, StackSpaceOperand(0)); 1171 __ lea(accessor_info_arg, StackSpaceOperand(0));
1160 1172
1161 Address getter_address = v8::ToCData<Address>(callback->getter()); 1173 Address getter_address = v8::ToCData<Address>(callback->getter());
1162 __ CallApiFunctionAndReturn(getter_address, kStackSpace); 1174 __ CallApiFunctionAndReturn(getter_address, kStackSpace);
1163 } 1175 }
1164 1176
1165 1177
1166 void StubCompiler::GenerateLoadConstant(Handle<JSObject> object, 1178 void BaseLoadStubCompiler::GenerateLoadConstant(Handle<JSFunction> value) {
1167 Handle<JSObject> holder,
1168 Register receiver,
1169 Register scratch1,
1170 Register scratch2,
1171 Register scratch3,
1172 Handle<JSFunction> value,
1173 Handle<String> name,
1174 Label* miss) {
1175 // Check that the receiver isn't a smi.
1176 __ JumpIfSmi(receiver, miss);
1177
1178 // Check that the maps haven't changed.
1179 CheckPrototypes(
1180 object, receiver, holder, scratch1, scratch2, scratch3, name, miss);
1181
1182 // Return the constant value. 1179 // Return the constant value.
1183 __ LoadHeapObject(rax, value); 1180 __ LoadHeapObject(rax, value);
1184 __ ret(0); 1181 __ ret(0);
1185 } 1182 }
1186 1183
1187 1184
1188 void StubCompiler::GenerateLoadInterceptor(Handle<JSObject> object, 1185 void BaseLoadStubCompiler::GenerateLoadInterceptor(
1189 Handle<JSObject> interceptor_holder, 1186 Register holder_reg,
1190 LookupResult* lookup, 1187 Handle<JSObject> object,
1191 Register receiver, 1188 Handle<JSObject> interceptor_holder,
1192 Register name_reg, 1189 LookupResult* lookup,
1193 Register scratch1, 1190 Handle<String> name) {
1194 Register scratch2,
1195 Register scratch3,
1196 Handle<String> name,
1197 Label* miss) {
1198 ASSERT(interceptor_holder->HasNamedInterceptor()); 1191 ASSERT(interceptor_holder->HasNamedInterceptor());
1199 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); 1192 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined());
1200 1193
1201 // Check that the receiver isn't a smi.
1202 __ JumpIfSmi(receiver, miss);
1203
1204 // So far the most popular follow ups for interceptor loads are FIELD 1194 // So far the most popular follow ups for interceptor loads are FIELD
1205 // and CALLBACKS, so inline only them, other cases may be added 1195 // and CALLBACKS, so inline only them, other cases may be added
1206 // later. 1196 // later.
1207 bool compile_followup_inline = false; 1197 bool compile_followup_inline = false;
1208 if (lookup->IsFound() && lookup->IsCacheable()) { 1198 if (lookup->IsFound() && lookup->IsCacheable()) {
1209 if (lookup->IsField()) { 1199 if (lookup->IsField()) {
1210 compile_followup_inline = true; 1200 compile_followup_inline = true;
1211 } else if (lookup->type() == CALLBACKS && 1201 } else if (lookup->type() == CALLBACKS &&
1212 lookup->GetCallbackObject()->IsAccessorInfo()) { 1202 lookup->GetCallbackObject()->IsAccessorInfo()) {
1213 AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject()); 1203 AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject());
1214 compile_followup_inline = callback->getter() != NULL && 1204 compile_followup_inline = callback->getter() != NULL &&
1215 callback->IsCompatibleReceiver(*object); 1205 callback->IsCompatibleReceiver(*object);
1216 } 1206 }
1217 } 1207 }
1218 1208
1219 if (compile_followup_inline) { 1209 if (compile_followup_inline) {
1220 // Compile the interceptor call, followed by inline code to load the 1210 // Compile the interceptor call, followed by inline code to load the
1221 // property from further up the prototype chain if the call fails. 1211 // property from further up the prototype chain if the call fails.
1222 // Check that the maps haven't changed. 1212 // Check that the maps haven't changed.
1223 Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder, 1213 ASSERT(holder_reg.is(receiver()) || holder_reg.is(scratch1()));
1224 scratch1, scratch2, scratch3,
1225 name, miss);
1226 ASSERT(holder_reg.is(receiver) || holder_reg.is(scratch1));
1227 1214
1228 // Preserve the receiver register explicitly whenever it is different from 1215 // Preserve the receiver register explicitly whenever it is different from
1229 // the holder and it is needed should the interceptor return without any 1216 // the holder and it is needed should the interceptor return without any
1230 // result. The CALLBACKS case needs the receiver to be passed into C++ code, 1217 // result. The CALLBACKS case needs the receiver to be passed into C++ code,
1231 // the FIELD case might cause a miss during the prototype check. 1218 // the FIELD case might cause a miss during the prototype check.
1232 bool must_perfrom_prototype_check = *interceptor_holder != lookup->holder(); 1219 bool must_perfrom_prototype_check = *interceptor_holder != lookup->holder();
1233 bool must_preserve_receiver_reg = !receiver.is(holder_reg) && 1220 bool must_preserve_receiver_reg = !receiver().is(holder_reg) &&
1234 (lookup->type() == CALLBACKS || must_perfrom_prototype_check); 1221 (lookup->type() == CALLBACKS || must_perfrom_prototype_check);
1235 1222
1236 // Save necessary data before invoking an interceptor. 1223 // Save necessary data before invoking an interceptor.
1237 // Requires a frame to make GC aware of pushed pointers. 1224 // Requires a frame to make GC aware of pushed pointers.
1238 { 1225 {
1239 FrameScope frame_scope(masm(), StackFrame::INTERNAL); 1226 FrameScope frame_scope(masm(), StackFrame::INTERNAL);
1240 1227
1241 if (must_preserve_receiver_reg) { 1228 if (must_preserve_receiver_reg) {
1242 __ push(receiver); 1229 __ push(receiver());
1243 } 1230 }
1244 __ push(holder_reg); 1231 __ push(holder_reg);
1245 __ push(name_reg); 1232 __ push(this->name());
1246 1233
1247 // Invoke an interceptor. Note: map checks from receiver to 1234 // Invoke an interceptor. Note: map checks from receiver to
1248 // interceptor's holder has been compiled before (see a caller 1235 // interceptor's holder has been compiled before (see a caller
1249 // of this method.) 1236 // of this method.)
1250 CompileCallLoadPropertyWithInterceptor(masm(), 1237 CompileCallLoadPropertyWithInterceptor(masm(),
1251 receiver, 1238 receiver(),
1252 holder_reg, 1239 holder_reg,
1253 name_reg, 1240 this->name(),
1254 interceptor_holder); 1241 interceptor_holder);
1255 1242
1256 // Check if interceptor provided a value for property. If it's 1243 // Check if interceptor provided a value for property. If it's
1257 // the case, return immediately. 1244 // the case, return immediately.
1258 Label interceptor_failed; 1245 Label interceptor_failed;
1259 __ CompareRoot(rax, Heap::kNoInterceptorResultSentinelRootIndex); 1246 __ CompareRoot(rax, Heap::kNoInterceptorResultSentinelRootIndex);
1260 __ j(equal, &interceptor_failed); 1247 __ j(equal, &interceptor_failed);
1261 frame_scope.GenerateLeaveFrame(); 1248 frame_scope.GenerateLeaveFrame();
1262 __ ret(0); 1249 __ ret(0);
1263 1250
1264 __ bind(&interceptor_failed); 1251 __ bind(&interceptor_failed);
1265 __ pop(name_reg); 1252 __ pop(this->name());
1266 __ pop(holder_reg); 1253 __ pop(holder_reg);
1267 if (must_preserve_receiver_reg) { 1254 if (must_preserve_receiver_reg) {
1268 __ pop(receiver); 1255 __ pop(receiver());
1269 } 1256 }
1270 1257
1271 // Leave the internal frame. 1258 // Leave the internal frame.
1272 } 1259 }
1273 1260
1274 // Check that the maps from interceptor's holder to lookup's holder 1261 GenerateLoadPostInterceptor(holder_reg, interceptor_holder, name, lookup);
1275 // haven't changed. And load lookup's holder into |holder| register.
1276 if (must_perfrom_prototype_check) {
1277 holder_reg = CheckPrototypes(interceptor_holder,
1278 holder_reg,
1279 Handle<JSObject>(lookup->holder()),
1280 scratch1,
1281 scratch2,
1282 scratch3,
1283 name,
1284 miss);
1285 }
1286
1287 if (lookup->IsField()) {
1288 // We found FIELD property in prototype chain of interceptor's holder.
1289 // Retrieve a field from field's holder.
1290 GenerateFastPropertyLoad(masm(), rax, holder_reg,
1291 Handle<JSObject>(lookup->holder()),
1292 lookup->GetFieldIndex());
1293 __ ret(0);
1294 } else {
1295 // We found CALLBACKS property in prototype chain of interceptor's
1296 // holder.
1297 ASSERT(lookup->type() == CALLBACKS);
1298 Handle<AccessorInfo> callback(
1299 AccessorInfo::cast(lookup->GetCallbackObject()));
1300 ASSERT(callback->getter() != NULL);
1301
1302 // Tail call to runtime.
1303 // Important invariant in CALLBACKS case: the code above must be
1304 // structured to never clobber |receiver| register.
1305 __ pop(scratch2); // return address
1306 __ push(receiver);
1307 __ push(holder_reg);
1308 __ Move(holder_reg, callback);
1309 __ push(FieldOperand(holder_reg, AccessorInfo::kDataOffset));
1310 __ PushAddress(ExternalReference::isolate_address());
1311 __ push(holder_reg);
1312 __ push(name_reg);
1313 __ push(scratch2); // restore return address
1314
1315 ExternalReference ref =
1316 ExternalReference(IC_Utility(IC::kLoadCallbackProperty),
1317 isolate());
1318 __ TailCallExternalReference(ref, 6, 1);
1319 }
1320 } else { // !compile_followup_inline 1262 } else { // !compile_followup_inline
1321 // Call the runtime system to load the interceptor. 1263 // Call the runtime system to load the interceptor.
1322 // Check that the maps haven't changed. 1264 // Check that the maps haven't changed.
1323 Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder, 1265 __ pop(scratch2()); // save old return address
1324 scratch1, scratch2, scratch3, 1266 PushInterceptorArguments(masm(), receiver(), holder_reg,
1325 name, miss); 1267 this->name(), interceptor_holder);
1326 __ pop(scratch2); // save old return address 1268 __ push(scratch2()); // restore old return address
1327 PushInterceptorArguments(masm(), receiver, holder_reg,
1328 name_reg, interceptor_holder);
1329 __ push(scratch2); // restore old return address
1330 1269
1331 ExternalReference ref = ExternalReference( 1270 ExternalReference ref = ExternalReference(
1332 IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), isolate()); 1271 IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), isolate());
1333 __ TailCallExternalReference(ref, 6, 1); 1272 __ TailCallExternalReference(ref, 6, 1);
1334 } 1273 }
1335 } 1274 }
1336 1275
1337 1276
1338 void CallStubCompiler::GenerateNameCheck(Handle<String> name, Label* miss) { 1277 void CallStubCompiler::GenerateNameCheck(Handle<String> name, Label* miss) {
1339 if (kind_ == Code::KEYED_CALL_IC) { 1278 if (kind_ == Code::KEYED_CALL_IC) {
(...skipping 1448 matching lines...) Expand 10 before | Expand all | Expand 10 after
2788 // Return the generated code. 2727 // Return the generated code.
2789 return GetCode(Code::NORMAL, factory()->empty_string(), POLYMORPHIC); 2728 return GetCode(Code::NORMAL, factory()->empty_string(), POLYMORPHIC);
2790 } 2729 }
2791 2730
2792 2731
2793 Handle<Code> LoadStubCompiler::CompileLoadNonexistent( 2732 Handle<Code> LoadStubCompiler::CompileLoadNonexistent(
2794 Handle<JSObject> object, 2733 Handle<JSObject> object,
2795 Handle<JSObject> last, 2734 Handle<JSObject> last,
2796 Handle<String> name, 2735 Handle<String> name,
2797 Handle<GlobalObject> global) { 2736 Handle<GlobalObject> global) {
2798 // ----------- S t a t e ------------- 2737 Label success;
2799 // -- rax : receiver
2800 // -- rcx : name
2801 // -- rsp[0] : return address
2802 // -----------------------------------
2803 Label miss;
2804 2738
2805 // Check that receiver is not a smi. 2739 NonexistentHandlerFrontend(object, last, name, &success, global);
2806 __ JumpIfSmi(rax, &miss);
2807 2740
2808 // Check the maps of the full prototype chain. Also check that 2741 __ bind(&success);
2809 // global property cells up to (but not including) the last object
2810 // in the prototype chain are empty.
2811 Register scratch = rdx;
2812 Register result =
2813 CheckPrototypes(object, rax, last, rbx, scratch, rdi, name, &miss);
2814
2815 // If the last object in the prototype chain is a global object,
2816 // check that the global property cell is empty.
2817 if (!global.is_null()) {
2818 GenerateCheckPropertyCell(masm(), global, name, scratch, &miss);
2819 }
2820
2821 if (!last->HasFastProperties()) {
2822 __ movq(scratch, FieldOperand(result, HeapObject::kMapOffset));
2823 __ movq(scratch, FieldOperand(scratch, Map::kPrototypeOffset));
2824 __ Cmp(scratch, isolate()->factory()->null_value());
2825 __ j(not_equal, &miss);
2826 }
2827
2828 // Return undefined if maps of the full prototype chain are still the 2742 // Return undefined if maps of the full prototype chain are still the
2829 // same and no global property with this name contains a value. 2743 // same and no global property with this name contains a value.
2830 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); 2744 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
2831 __ ret(0); 2745 __ ret(0);
2832 2746
2833 __ bind(&miss);
2834 GenerateLoadMiss(masm(), Code::LOAD_IC);
2835
2836 // Return the generated code. 2747 // Return the generated code.
2837 return GetCode(Code::NONEXISTENT, factory()->empty_string()); 2748 return GetCode(Code::NONEXISTENT, factory()->empty_string());
2838 } 2749 }
2839 2750
2840 2751
2841 Register* LoadStubCompiler::registers() { 2752 Register* LoadStubCompiler::registers() {
2842 // receiver, name, scratch1, scratch2, scratch3, scratch4. 2753 // receiver, name, scratch1, scratch2, scratch3, scratch4.
2843 static Register registers[] = { rax, rcx, rdx, rbx, rdi, r8 }; 2754 static Register registers[] = { rax, rcx, rdx, rbx, rdi, r8 };
2844 return registers; 2755 return registers;
2845 } 2756 }
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
2890 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 2801 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
2891 } 2802 }
2892 __ ret(0); 2803 __ ret(0);
2893 } 2804 }
2894 2805
2895 2806
2896 #undef __ 2807 #undef __
2897 #define __ ACCESS_MASM(masm()) 2808 #define __ ACCESS_MASM(masm())
2898 2809
2899 2810
2900 Handle<Code> LoadStubCompiler::CompileLoadViaGetter(
2901 Handle<JSObject> receiver,
2902 Handle<JSObject> holder,
2903 Handle<String> name,
2904 Handle<JSFunction> getter) {
2905 // ----------- S t a t e -------------
2906 // -- rax : receiver
2907 // -- rcx : name
2908 // -- rsp[0] : return address
2909 // -----------------------------------
2910 Label miss;
2911
2912 // Check that the maps haven't changed.
2913 __ JumpIfSmi(rax, &miss);
2914 CheckPrototypes(receiver, rax, holder, rbx, rdx, rdi, name, &miss);
2915
2916 GenerateLoadViaGetter(masm(), getter),
2917
2918 __ bind(&miss);
2919 GenerateLoadMiss(masm(), Code::LOAD_IC);
2920
2921 // Return the generated code.
2922 return GetCode(Code::CALLBACKS, name);
2923 }
2924
2925
2926 Handle<Code> LoadStubCompiler::CompileLoadGlobal( 2811 Handle<Code> LoadStubCompiler::CompileLoadGlobal(
2927 Handle<JSObject> object, 2812 Handle<JSObject> object,
2928 Handle<GlobalObject> holder, 2813 Handle<GlobalObject> global,
2929 Handle<JSGlobalPropertyCell> cell, 2814 Handle<JSGlobalPropertyCell> cell,
2930 Handle<String> name, 2815 Handle<String> name,
2931 bool is_dont_delete) { 2816 bool is_dont_delete) {
2932 // ----------- S t a t e ------------- 2817 Label success, miss;
2933 // -- rax : receiver 2818 // TODO(verwaest): Directly store to rax. Currently we cannot do this, since
2934 // -- rcx : name 2819 // rax is used as receiver(), which we would otherwise clobber before a
2935 // -- rsp[0] : return address 2820 // potential miss.
2936 // -----------------------------------
2937 Label miss;
2938 2821
2939 // Check that the maps haven't changed. 2822 HandlerFrontendHeader(object, receiver(), Handle<JSObject>::cast(global),
2940 __ JumpIfSmi(rax, &miss); 2823 name, &miss, PERFORM_INITIAL_CHECKS);
2941 CheckPrototypes(object, rax, holder, rbx, rdx, rdi, name, &miss);
2942 2824
2943 // Get the value from the cell. 2825 // Get the value from the cell.
2944 __ Move(rbx, cell); 2826 __ Move(rbx, cell);
2945 __ movq(rbx, FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset)); 2827 __ movq(rbx, FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset));
2946 2828
2947 // Check for deleted property if property can actually be deleted. 2829 // Check for deleted property if property can actually be deleted.
2948 if (!is_dont_delete) { 2830 if (!is_dont_delete) {
2949 __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex); 2831 __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex);
2950 __ j(equal, &miss); 2832 __ j(equal, &miss);
2951 } else if (FLAG_debug_code) { 2833 } else if (FLAG_debug_code) {
2952 __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex); 2834 __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex);
2953 __ Check(not_equal, "DontDelete cells can't contain the hole"); 2835 __ Check(not_equal, "DontDelete cells can't contain the hole");
2954 } 2836 }
2955 2837
2838 HandlerFrontendFooter(&success, &miss);
2839 __ bind(&success);
2840
2956 Counters* counters = isolate()->counters(); 2841 Counters* counters = isolate()->counters();
2957 __ IncrementCounter(counters->named_load_global_stub(), 1); 2842 __ IncrementCounter(counters->named_load_global_stub(), 1);
2958 __ movq(rax, rbx); 2843 __ movq(rax, rbx);
2959 __ ret(0); 2844 __ ret(0);
2960 2845
2961 __ bind(&miss);
2962 __ IncrementCounter(counters->named_load_global_stub_miss(), 1);
2963 GenerateLoadMiss(masm(), Code::LOAD_IC);
2964
2965 // Return the generated code. 2846 // Return the generated code.
2966 return GetCode(Code::NORMAL, name); 2847 return GetCode(Code::NORMAL, name);
2967 } 2848 }
2968 2849
2969 2850
2970 Handle<Code> KeyedLoadStubCompiler::CompileLoadElement( 2851 Handle<Code> KeyedLoadStubCompiler::CompileLoadElement(
2971 Handle<Map> receiver_map) { 2852 Handle<Map> receiver_map) {
2972 // ----------- S t a t e ------------- 2853 // ----------- S t a t e -------------
2973 // -- rax : key 2854 // -- rax : key
2974 // -- rdx : receiver 2855 // -- rdx : receiver
(...skipping 718 matching lines...) Expand 10 before | Expand all | Expand 10 after
3693 __ jmp(ic_slow, RelocInfo::CODE_TARGET); 3574 __ jmp(ic_slow, RelocInfo::CODE_TARGET);
3694 } 3575 }
3695 } 3576 }
3696 3577
3697 3578
3698 #undef __ 3579 #undef __
3699 3580
3700 } } // namespace v8::internal 3581 } } // namespace v8::internal
3701 3582
3702 #endif // V8_TARGET_ARCH_X64 3583 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/stub-cache.cc ('k') | test/cctest/test-serialize.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698