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

Side by Side Diff: src/ic.cc

Issue 26873002: Remove BaseLoad/StoreStub compilers, and the stub-cache interface duplication. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 7 years, 2 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
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 1087 matching lines...) Expand 10 before | Expand all | Expand 10 after
1098 break; 1098 break;
1099 case DEBUG_STUB: 1099 case DEBUG_STUB:
1100 break; 1100 break;
1101 case GENERIC: 1101 case GENERIC:
1102 UNREACHABLE(); 1102 UNREACHABLE();
1103 break; 1103 break;
1104 } 1104 }
1105 } 1105 }
1106 1106
1107 1107
1108 Handle<Code> LoadIC::SimpleFieldLoad(int offset,
1109 bool inobject,
1110 Representation representation) {
1111 if (kind() == Code::LOAD_IC) {
1112 LoadFieldStub stub(inobject, offset, representation);
1113 return stub.GetCode(isolate());
1114 } else {
1115 KeyedLoadFieldStub stub(inobject, offset, representation);
1116 return stub.GetCode(isolate());
1117 }
1118 }
1119
1108 void LoadIC::UpdateCaches(LookupResult* lookup, 1120 void LoadIC::UpdateCaches(LookupResult* lookup,
1109 Handle<Object> object, 1121 Handle<Object> object,
1110 Handle<String> name) { 1122 Handle<String> name) {
1111 // TODO(verwaest): It would be nice to support loading fields from smis as 1123 // TODO(verwaest): It would be nice to support loading fields from smis as
1112 // well. For now just fail to update the cache. 1124 // well. For now just fail to update the cache.
1113 if (!object->IsHeapObject()) return; 1125 if (!object->IsHeapObject()) return;
1114 1126
1115 Handle<HeapObject> receiver = Handle<HeapObject>::cast(object); 1127 Handle<HeapObject> receiver = Handle<HeapObject>::cast(object);
1116 1128
1117 Handle<Code> code; 1129 Handle<Code> code;
1118 if (state() == UNINITIALIZED) { 1130 if (state() == UNINITIALIZED) {
1119 // This is the first time we execute this inline cache. 1131 // This is the first time we execute this inline cache.
1120 // Set the target to the pre monomorphic stub to delay 1132 // Set the target to the pre monomorphic stub to delay
1121 // setting the monomorphic state. 1133 // setting the monomorphic state.
1122 code = pre_monomorphic_stub(); 1134 code = pre_monomorphic_stub();
1123 } else if (!lookup->IsCacheable()) { 1135 } else if (!lookup->IsCacheable()) {
1124 // Bail out if the result is not cacheable. 1136 // Bail out if the result is not cacheable.
1125 code = slow_stub(); 1137 code = slow_stub();
1126 } else if (object->IsString() && 1138 } else if (object->IsString() &&
1127 name->Equals(isolate()->heap()->length_string())) { 1139 name->Equals(isolate()->heap()->length_string())) {
1128 int length_index = String::kLengthOffset / kPointerSize; 1140 int length_index = String::kLengthOffset / kPointerSize;
1129 if (target()->is_load_stub()) { 1141 code = SimpleFieldLoad(length_index);
1130 LoadFieldStub stub(true, length_index, Representation::Tagged());
1131 code = stub.GetCode(isolate());
1132 } else {
1133 KeyedLoadFieldStub stub(true, length_index, Representation::Tagged());
1134 code = stub.GetCode(isolate());
1135 }
1136 } else if (!object->IsJSObject()) { 1142 } else if (!object->IsJSObject()) {
1137 // TODO(jkummerow): It would be nice to support non-JSObjects in 1143 // TODO(jkummerow): It would be nice to support non-JSObjects in
1138 // ComputeLoadHandler, then we wouldn't need to go generic here. 1144 // ComputeLoadHandler, then we wouldn't need to go generic here.
1139 code = slow_stub(); 1145 code = slow_stub();
1140 } else if (!lookup->IsProperty()) { 1146 } else if (!lookup->IsProperty()) {
1141 code = kind() == Code::LOAD_IC 1147 code = kind() == Code::LOAD_IC
1142 ? isolate()->stub_cache()->ComputeLoadNonexistent( 1148 ? isolate()->stub_cache()->ComputeLoadNonexistent(
1143 name, Handle<JSObject>::cast(receiver)) 1149 name, Handle<JSObject>::cast(receiver))
1144 : slow_stub(); 1150 : slow_stub();
1145 } else { 1151 } else {
(...skipping 14 matching lines...) Expand all
1160 1166
1161 Handle<Code> IC::ComputeHandler(LookupResult* lookup, 1167 Handle<Code> IC::ComputeHandler(LookupResult* lookup,
1162 Handle<JSObject> receiver, 1168 Handle<JSObject> receiver,
1163 Handle<String> name, 1169 Handle<String> name,
1164 Handle<Object> value) { 1170 Handle<Object> value) {
1165 Handle<Code> code = isolate()->stub_cache()->FindHandler( 1171 Handle<Code> code = isolate()->stub_cache()->FindHandler(
1166 name, receiver, kind()); 1172 name, receiver, kind());
1167 if (!code.is_null()) return code; 1173 if (!code.is_null()) return code;
1168 1174
1169 code = CompileHandler(lookup, receiver, name, value); 1175 code = CompileHandler(lookup, receiver, name, value);
1170 if (code.is_null()) return slow_stub();
1171 1176
1172 if (code->is_handler() && code->type() != Code::NORMAL) { 1177 if (code->is_handler() && code->type() != Code::NORMAL) {
1173 HeapObject::UpdateMapCodeCache(receiver, name, code); 1178 HeapObject::UpdateMapCodeCache(receiver, name, code);
1174 } 1179 }
1175 1180
1176 return code; 1181 return code;
1177 } 1182 }
1178 1183
1179 1184
1180 Handle<Code> LoadIC::CompileHandler(LookupResult* lookup, 1185 Handle<Code> LoadIC::CompileHandler(LookupResult* lookup,
1181 Handle<JSObject> receiver, 1186 Handle<JSObject> receiver,
1182 Handle<String> name, 1187 Handle<String> name,
1183 Handle<Object> unused) { 1188 Handle<Object> unused) {
1184 Handle<JSObject> holder(lookup->holder()); 1189 Handle<JSObject> holder(lookup->holder());
1190 LoadStubCompiler compiler(isolate(), kind());
1191
1185 switch (lookup->type()) { 1192 switch (lookup->type()) {
1186 case FIELD: 1193 case FIELD: {
1187 return isolate()->stub_cache()->ComputeLoadField( 1194 PropertyIndex field = lookup->GetFieldIndex();
1188 name, receiver, holder, 1195 if (receiver.is_identical_to(holder)) {
1189 lookup->GetFieldIndex(), lookup->representation()); 1196 return SimpleFieldLoad(field.translate(holder),
1197 field.is_inobject(holder),
1198 lookup->representation());
1199 }
1200 return compiler.CompileLoadField(
1201 receiver, holder, name, field, lookup->representation());
1202 }
1190 case CONSTANT: { 1203 case CONSTANT: {
1191 Handle<Object> constant(lookup->GetConstant(), isolate()); 1204 Handle<Object> constant(lookup->GetConstant(), isolate());
1192 // TODO(2803): Don't compute a stub for cons strings because they cannot 1205 // TODO(2803): Don't compute a stub for cons strings because they cannot
1193 // be embedded into code. 1206 // be embedded into code.
1194 if (constant->IsConsString()) return Handle<Code>::null(); 1207 if (constant->IsConsString()) break;
1195 return isolate()->stub_cache()->ComputeLoadConstant( 1208 return compiler.CompileLoadConstant(receiver, holder, name, constant);
1196 name, receiver, holder, constant);
1197 } 1209 }
1198 case NORMAL: 1210 case NORMAL:
1211 if (kind() != Code::LOAD_IC) break;
1199 if (holder->IsGlobalObject()) { 1212 if (holder->IsGlobalObject()) {
1200 Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder); 1213 Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder);
1201 Handle<PropertyCell> cell( 1214 Handle<PropertyCell> cell(
1202 global->GetPropertyCell(lookup), isolate()); 1215 global->GetPropertyCell(lookup), isolate());
1216 // TODO(verwaest): Turn into a handler.
1203 return isolate()->stub_cache()->ComputeLoadGlobal( 1217 return isolate()->stub_cache()->ComputeLoadGlobal(
1204 name, receiver, global, cell, lookup->IsDontDelete()); 1218 name, receiver, global, cell, lookup->IsDontDelete());
1205 } 1219 }
1206 // There is only one shared stub for loading normalized 1220 // There is only one shared stub for loading normalized
1207 // properties. It does not traverse the prototype chain, so the 1221 // properties. It does not traverse the prototype chain, so the
1208 // property must be found in the receiver for the stub to be 1222 // property must be found in the receiver for the stub to be
1209 // applicable. 1223 // applicable.
1210 if (!holder.is_identical_to(receiver)) break; 1224 if (!holder.is_identical_to(receiver)) break;
1211 return isolate()->stub_cache()->ComputeLoadNormal(name, receiver); 1225 return isolate()->builtins()->LoadIC_Normal();
1212 case CALLBACKS: { 1226 case CALLBACKS: {
1213 { 1227 // Use simple field loads for some well-known callback properties.
1214 // Use simple field loads for some well-known callback properties. 1228 int object_offset;
1215 int object_offset; 1229 Handle<Map> map(receiver->map());
1216 Handle<Map> map(receiver->map()); 1230 if (Accessors::IsJSObjectFieldAccessor(map, name, &object_offset)) {
1217 if (Accessors::IsJSObjectFieldAccessor(map, name, &object_offset)) { 1231 PropertyIndex index =
1218 PropertyIndex index = 1232 PropertyIndex::NewHeaderIndex(object_offset / kPointerSize);
1219 PropertyIndex::NewHeaderIndex(object_offset / kPointerSize); 1233 return compiler.CompileLoadField(
1220 return isolate()->stub_cache()->ComputeLoadField( 1234 receiver, receiver, name, index, Representation::Tagged());
1221 name, receiver, receiver, index, Representation::Tagged());
1222 }
1223 } 1235 }
1224 1236
1225 Handle<Object> callback(lookup->GetCallbackObject(), isolate()); 1237 Handle<Object> callback(lookup->GetCallbackObject(), isolate());
1226 if (callback->IsExecutableAccessorInfo()) { 1238 if (callback->IsExecutableAccessorInfo()) {
1227 Handle<ExecutableAccessorInfo> info = 1239 Handle<ExecutableAccessorInfo> info =
1228 Handle<ExecutableAccessorInfo>::cast(callback); 1240 Handle<ExecutableAccessorInfo>::cast(callback);
1229 if (v8::ToCData<Address>(info->getter()) == 0) break; 1241 if (v8::ToCData<Address>(info->getter()) == 0) break;
1230 if (!info->IsCompatibleReceiver(*receiver)) break; 1242 if (!info->IsCompatibleReceiver(*receiver)) break;
1231 return isolate()->stub_cache()->ComputeLoadCallback( 1243 return compiler.CompileLoadCallback(receiver, holder, name, info);
1232 name, receiver, holder, info);
1233 } else if (callback->IsAccessorPair()) { 1244 } else if (callback->IsAccessorPair()) {
1234 Handle<Object> getter(Handle<AccessorPair>::cast(callback)->getter(), 1245 Handle<Object> getter(Handle<AccessorPair>::cast(callback)->getter(),
1235 isolate()); 1246 isolate());
1236 if (!getter->IsJSFunction()) break; 1247 if (!getter->IsJSFunction()) break;
1237 if (holder->IsGlobalObject()) break; 1248 if (holder->IsGlobalObject()) break;
1238 if (!holder->HasFastProperties()) break; 1249 if (!holder->HasFastProperties()) break;
1239 Handle<JSFunction> function = Handle<JSFunction>::cast(getter); 1250 Handle<JSFunction> function = Handle<JSFunction>::cast(getter);
1240 CallOptimization call_optimization(function); 1251 CallOptimization call_optimization(function);
1241 if (call_optimization.is_simple_api_call() && 1252 if (call_optimization.is_simple_api_call() &&
1242 call_optimization.IsCompatibleReceiver(*receiver)) { 1253 call_optimization.IsCompatibleReceiver(*receiver)) {
1243 return isolate()->stub_cache()->ComputeLoadCallback( 1254 return compiler.CompileLoadCallback(
1244 name, receiver, holder, call_optimization); 1255 receiver, holder, name, call_optimization);
1245 } 1256 }
1246 return isolate()->stub_cache()->ComputeLoadViaGetter( 1257 return compiler.CompileLoadViaGetter(receiver, holder, name, function);
1247 name, receiver, holder, function);
1248 } 1258 }
1249 // TODO(dcarney): Handle correctly. 1259 // TODO(dcarney): Handle correctly.
1250 if (callback->IsDeclaredAccessorInfo()) break; 1260 if (callback->IsDeclaredAccessorInfo()) break;
1251 ASSERT(callback->IsForeign()); 1261 ASSERT(callback->IsForeign());
1252 // No IC support for old-style native accessors. 1262 // No IC support for old-style native accessors.
1253 break; 1263 break;
1254 } 1264 }
1255 case INTERCEPTOR: 1265 case INTERCEPTOR:
1256 ASSERT(HasInterceptorGetter(*holder)); 1266 ASSERT(HasInterceptorGetter(*holder));
1257 return isolate()->stub_cache()->ComputeLoadInterceptor( 1267 return compiler.CompileLoadInterceptor(receiver, holder, name);
1258 name, receiver, holder);
1259 default: 1268 default:
1260 break; 1269 break;
1261 } 1270 }
1262 return Handle<Code>::null(); 1271
1272 return slow_stub();
1263 } 1273 }
1264 1274
1265 1275
1266 static Handle<Object> TryConvertKey(Handle<Object> key, Isolate* isolate) { 1276 static Handle<Object> TryConvertKey(Handle<Object> key, Isolate* isolate) {
1267 // This helper implements a few common fast cases for converting 1277 // This helper implements a few common fast cases for converting
1268 // non-smi keys of keyed loads/stores to a smi or a string. 1278 // non-smi keys of keyed loads/stores to a smi or a string.
1269 if (key->IsHeapNumber()) { 1279 if (key->IsHeapNumber()) {
1270 double value = Handle<HeapNumber>::cast(key)->value(); 1280 double value = Handle<HeapNumber>::cast(key)->value();
1271 if (std::isnan(value)) { 1281 if (std::isnan(value)) {
1272 key = isolate->factory()->nan_string(); 1282 key = isolate->factory()->nan_string();
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
1384 ASSERT(!stub.is_null()); 1394 ASSERT(!stub.is_null());
1385 set_target(*stub); 1395 set_target(*stub);
1386 TRACE_IC("LoadIC", key); 1396 TRACE_IC("LoadIC", key);
1387 } 1397 }
1388 1398
1389 1399
1390 return Runtime::GetObjectPropertyOrFail(isolate(), object, key); 1400 return Runtime::GetObjectPropertyOrFail(isolate(), object, key);
1391 } 1401 }
1392 1402
1393 1403
1394 Handle<Code> KeyedLoadIC::CompileHandler(LookupResult* lookup,
1395 Handle<JSObject> receiver,
1396 Handle<String> name,
1397 Handle<Object> value) {
1398 // Compute a monomorphic stub.
1399 Handle<JSObject> holder(lookup->holder(), isolate());
1400 switch (lookup->type()) {
1401 case FIELD:
1402 return isolate()->stub_cache()->ComputeKeyedLoadField(
1403 name, receiver, holder,
1404 lookup->GetFieldIndex(), lookup->representation());
1405 case CONSTANT: {
1406 Handle<Object> constant(lookup->GetConstant(), isolate());
1407 // TODO(2803): Don't compute a stub for cons strings because they cannot
1408 // be embedded into code.
1409 if (constant->IsConsString()) return Handle<Code>::null();
1410 return isolate()->stub_cache()->ComputeKeyedLoadConstant(
1411 name, receiver, holder, constant);
1412 }
1413 case CALLBACKS: {
1414 Handle<Object> callback_object(lookup->GetCallbackObject(), isolate());
1415 // TODO(dcarney): Handle DeclaredAccessorInfo correctly.
1416 if (callback_object->IsExecutableAccessorInfo()) {
1417 Handle<ExecutableAccessorInfo> callback =
1418 Handle<ExecutableAccessorInfo>::cast(callback_object);
1419 if (v8::ToCData<Address>(callback->getter()) == 0) break;
1420 if (!callback->IsCompatibleReceiver(*receiver)) break;
1421 return isolate()->stub_cache()->ComputeKeyedLoadCallback(
1422 name, receiver, holder, callback);
1423 } else if (callback_object->IsAccessorPair()) {
1424 Handle<Object> getter(
1425 Handle<AccessorPair>::cast(callback_object)->getter(),
1426 isolate());
1427 if (!getter->IsJSFunction()) break;
1428 if (holder->IsGlobalObject()) break;
1429 if (!holder->HasFastProperties()) break;
1430 Handle<JSFunction> function = Handle<JSFunction>::cast(getter);
1431 CallOptimization call_optimization(function);
1432 if (call_optimization.is_simple_api_call() &&
1433 call_optimization.IsCompatibleReceiver(*receiver)) {
1434 return isolate()->stub_cache()->ComputeKeyedLoadCallback(
1435 name, receiver, holder, call_optimization);
1436 }
1437 }
1438 break;
1439 }
1440 case INTERCEPTOR:
1441 ASSERT(HasInterceptorGetter(lookup->holder()));
1442 return isolate()->stub_cache()->ComputeKeyedLoadInterceptor(
1443 name, receiver, holder);
1444 default:
1445 // Always rewrite to the generic case so that we do not
1446 // repeatedly try to rewrite.
1447 return generic_stub();
1448 }
1449 return Handle<Code>::null();
1450 }
1451
1452
1453 static bool LookupForWrite(Handle<JSObject> receiver, 1404 static bool LookupForWrite(Handle<JSObject> receiver,
1454 Handle<String> name, 1405 Handle<String> name,
1455 Handle<Object> value, 1406 Handle<Object> value,
1456 LookupResult* lookup, 1407 LookupResult* lookup,
1457 IC* ic) { 1408 IC* ic) {
1458 Handle<JSObject> holder = receiver; 1409 Handle<JSObject> holder = receiver;
1459 receiver->Lookup(*name, lookup); 1410 receiver->Lookup(*name, lookup);
1460 if (lookup->IsFound()) { 1411 if (lookup->IsFound()) {
1461 if (lookup->IsReadOnly() || !lookup->IsCacheable()) return false; 1412 if (lookup->IsReadOnly() || !lookup->IsCacheable()) return false;
1462 1413
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after
1640 PatchCache(receiver, name, code); 1591 PatchCache(receiver, name, code);
1641 TRACE_IC("StoreIC", name); 1592 TRACE_IC("StoreIC", name);
1642 } 1593 }
1643 1594
1644 1595
1645 Handle<Code> StoreIC::CompileHandler(LookupResult* lookup, 1596 Handle<Code> StoreIC::CompileHandler(LookupResult* lookup,
1646 Handle<JSObject> receiver, 1597 Handle<JSObject> receiver,
1647 Handle<String> name, 1598 Handle<String> name,
1648 Handle<Object> value) { 1599 Handle<Object> value) {
1649 Handle<JSObject> holder(lookup->holder()); 1600 Handle<JSObject> holder(lookup->holder());
1601 StoreStubCompiler compiler(isolate(), strict_mode(), kind());
1650 switch (lookup->type()) { 1602 switch (lookup->type()) {
1651 case FIELD: 1603 case FIELD:
1652 return isolate()->stub_cache()->ComputeStoreField( 1604 return compiler.CompileStoreField(receiver, lookup, name);
1653 name, receiver, lookup, strict_mode()); 1605 case TRANSITION: {
1606 // Explicitly pass in the receiver map since LookupForWrite may have
1607 // stored something else than the receiver in the holder.
1608 Handle<Map> transition(
1609 lookup->GetTransitionTarget(receiver->map()), isolate());
1610 int descriptor = transition->LastAdded();
1611
1612 DescriptorArray* target_descriptors = transition->instance_descriptors();
1613 PropertyDetails details = target_descriptors->GetDetails(descriptor);
1614
1615 if (details.type() == CALLBACKS || details.attributes() != NONE) break;
1616
1617 return compiler.CompileStoreTransition(
1618 receiver, lookup, transition, name);
1619 }
1654 case NORMAL: 1620 case NORMAL:
1621 if (kind() == Code::KEYED_STORE_IC) break;
1655 if (receiver->IsGlobalObject()) { 1622 if (receiver->IsGlobalObject()) {
1656 // The stub generated for the global object picks the value directly 1623 // The stub generated for the global object picks the value directly
1657 // from the property cell. So the property must be directly on the 1624 // from the property cell. So the property must be directly on the
1658 // global object. 1625 // global object.
1659 Handle<GlobalObject> global = Handle<GlobalObject>::cast(receiver); 1626 Handle<GlobalObject> global = Handle<GlobalObject>::cast(receiver);
1660 Handle<PropertyCell> cell( 1627 Handle<PropertyCell> cell(
1661 global->GetPropertyCell(lookup), isolate()); 1628 global->GetPropertyCell(lookup), isolate());
1629 // TODO(verwaest): Turn into a handler.
1662 return isolate()->stub_cache()->ComputeStoreGlobal( 1630 return isolate()->stub_cache()->ComputeStoreGlobal(
1663 name, global, cell, value, strict_mode()); 1631 name, global, cell, value, strict_mode());
1664 } 1632 }
1665 ASSERT(holder.is_identical_to(receiver)); 1633 ASSERT(holder.is_identical_to(receiver));
1666 return isolate()->stub_cache()->ComputeStoreNormal(strict_mode()); 1634 return strict_mode() == kStrictMode
1635 ? isolate()->builtins()->StoreIC_Normal_Strict()
1636 : isolate()->builtins()->StoreIC_Normal();
1667 case CALLBACKS: { 1637 case CALLBACKS: {
1638 if (kind() == Code::KEYED_STORE_IC) break;
1668 Handle<Object> callback(lookup->GetCallbackObject(), isolate()); 1639 Handle<Object> callback(lookup->GetCallbackObject(), isolate());
1669 if (callback->IsExecutableAccessorInfo()) { 1640 if (callback->IsExecutableAccessorInfo()) {
1670 Handle<ExecutableAccessorInfo> info = 1641 Handle<ExecutableAccessorInfo> info =
1671 Handle<ExecutableAccessorInfo>::cast(callback); 1642 Handle<ExecutableAccessorInfo>::cast(callback);
1672 if (v8::ToCData<Address>(info->setter()) == 0) break; 1643 if (v8::ToCData<Address>(info->setter()) == 0) break;
1673 if (!holder->HasFastProperties()) break; 1644 if (!holder->HasFastProperties()) break;
1674 if (!info->IsCompatibleReceiver(*receiver)) break; 1645 if (!info->IsCompatibleReceiver(*receiver)) break;
1675 return isolate()->stub_cache()->ComputeStoreCallback( 1646 return compiler.CompileStoreCallback(receiver, holder, name, info);
1676 name, receiver, holder, info, strict_mode());
1677 } else if (callback->IsAccessorPair()) { 1647 } else if (callback->IsAccessorPair()) {
1678 Handle<Object> setter( 1648 Handle<Object> setter(
1679 Handle<AccessorPair>::cast(callback)->setter(), isolate()); 1649 Handle<AccessorPair>::cast(callback)->setter(), isolate());
1680 if (!setter->IsJSFunction()) break; 1650 if (!setter->IsJSFunction()) break;
1681 if (holder->IsGlobalObject()) break; 1651 if (holder->IsGlobalObject()) break;
1682 if (!holder->HasFastProperties()) break; 1652 if (!holder->HasFastProperties()) break;
1683 Handle<JSFunction> function = Handle<JSFunction>::cast(setter); 1653 Handle<JSFunction> function = Handle<JSFunction>::cast(setter);
1684 CallOptimization call_optimization(function); 1654 CallOptimization call_optimization(function);
1685 if (call_optimization.is_simple_api_call() && 1655 if (call_optimization.is_simple_api_call() &&
1686 call_optimization.IsCompatibleReceiver(*receiver)) { 1656 call_optimization.IsCompatibleReceiver(*receiver)) {
1687 return isolate()->stub_cache()->ComputeStoreCallback( 1657 return compiler.CompileStoreCallback(
1688 name, receiver, holder, call_optimization, strict_mode()); 1658 receiver, holder, name, call_optimization);
1689 } 1659 }
1690 return isolate()->stub_cache()->ComputeStoreViaSetter( 1660 return compiler.CompileStoreViaSetter(
1691 name, receiver, holder, Handle<JSFunction>::cast(setter), 1661 receiver, holder, name, Handle<JSFunction>::cast(setter));
1692 strict_mode());
1693 } 1662 }
1694 // TODO(dcarney): Handle correctly. 1663 // TODO(dcarney): Handle correctly.
1695 if (callback->IsDeclaredAccessorInfo()) break; 1664 if (callback->IsDeclaredAccessorInfo()) break;
1696 ASSERT(callback->IsForeign()); 1665 ASSERT(callback->IsForeign());
1697 // No IC support for old-style native accessors. 1666 // No IC support for old-style native accessors.
1698 break; 1667 break;
1699 } 1668 }
1700 case INTERCEPTOR: 1669 case INTERCEPTOR:
1670 if (kind() == Code::KEYED_STORE_IC) break;
1701 ASSERT(HasInterceptorSetter(*receiver)); 1671 ASSERT(HasInterceptorSetter(*receiver));
1702 return isolate()->stub_cache()->ComputeStoreInterceptor( 1672 return compiler.CompileStoreInterceptor(receiver, name);
1703 name, receiver, strict_mode());
1704 case CONSTANT: 1673 case CONSTANT:
1705 break; 1674 break;
1706 case TRANSITION: {
1707 // Explicitly pass in the receiver map since LookupForWrite may have
1708 // stored something else than the receiver in the holder.
1709 Handle<Map> transition(
1710 lookup->GetTransitionTarget(receiver->map()), isolate());
1711 int descriptor = transition->LastAdded();
1712
1713 DescriptorArray* target_descriptors = transition->instance_descriptors();
1714 PropertyDetails details = target_descriptors->GetDetails(descriptor);
1715
1716 if (details.type() == CALLBACKS || details.attributes() != NONE) break;
1717
1718 return isolate()->stub_cache()->ComputeStoreTransition(
1719 name, receiver, lookup, transition, strict_mode());
1720 }
1721 case NONEXISTENT: 1675 case NONEXISTENT:
1722 case HANDLER: 1676 case HANDLER:
1723 UNREACHABLE(); 1677 UNREACHABLE();
1724 break; 1678 break;
1725 } 1679 }
1726 return Handle<Code>::null(); 1680 return slow_stub();
1727 } 1681 }
1728 1682
1729 1683
1730 Handle<Code> KeyedStoreIC::StoreElementStub(Handle<JSObject> receiver, 1684 Handle<Code> KeyedStoreIC::StoreElementStub(Handle<JSObject> receiver,
1731 KeyedAccessStoreMode store_mode) { 1685 KeyedAccessStoreMode store_mode) {
1732 // Don't handle megamorphic property accesses for INTERCEPTORS or CALLBACKS 1686 // Don't handle megamorphic property accesses for INTERCEPTORS or CALLBACKS
1733 // via megamorphic stubs, since they don't have a map in their relocation info 1687 // via megamorphic stubs, since they don't have a map in their relocation info
1734 // and so the stubs can't be harvested for the object needed for a map check. 1688 // and so the stubs can't be harvested for the object needed for a map check.
1735 if (target()->type() != Code::NORMAL) { 1689 if (target()->type() != Code::NORMAL) {
1736 TRACE_GENERIC_IC(isolate(), "KeyedIC", "non-NORMAL target type"); 1690 TRACE_GENERIC_IC(isolate(), "KeyedIC", "non-NORMAL target type");
(...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after
2027 ASSERT(!stub.is_null()); 1981 ASSERT(!stub.is_null());
2028 set_target(*stub); 1982 set_target(*stub);
2029 TRACE_IC("StoreIC", key); 1983 TRACE_IC("StoreIC", key);
2030 } 1984 }
2031 1985
2032 return Runtime::SetObjectPropertyOrFail( 1986 return Runtime::SetObjectPropertyOrFail(
2033 isolate(), object , key, value, NONE, strict_mode()); 1987 isolate(), object , key, value, NONE, strict_mode());
2034 } 1988 }
2035 1989
2036 1990
2037 Handle<Code> KeyedStoreIC::CompileHandler(LookupResult* lookup,
2038 Handle<JSObject> receiver,
2039 Handle<String> name,
2040 Handle<Object> value) {
2041 // If the property has a non-field type allowing map transitions
2042 // where there is extra room in the object, we leave the IC in its
2043 // current state.
2044 switch (lookup->type()) {
2045 case FIELD:
2046 return isolate()->stub_cache()->ComputeKeyedStoreField(
2047 name, receiver, lookup, strict_mode());
2048 case TRANSITION: {
2049 // Explicitly pass in the receiver map since LookupForWrite may have
2050 // stored something else than the receiver in the holder.
2051 Handle<Map> transition(
2052 lookup->GetTransitionTarget(receiver->map()), isolate());
2053 int descriptor = transition->LastAdded();
2054
2055 DescriptorArray* target_descriptors = transition->instance_descriptors();
2056 PropertyDetails details = target_descriptors->GetDetails(descriptor);
2057
2058 if (details.type() != CALLBACKS && details.attributes() == NONE) {
2059 return isolate()->stub_cache()->ComputeKeyedStoreTransition(
2060 name, receiver, lookup, transition, strict_mode());
2061 }
2062 // fall through.
2063 }
2064 case NORMAL:
2065 case CONSTANT:
2066 case CALLBACKS:
2067 case INTERCEPTOR:
2068 // Always rewrite to the generic case so that we do not
2069 // repeatedly try to rewrite.
2070 return generic_stub();
2071 case HANDLER:
2072 case NONEXISTENT:
2073 UNREACHABLE();
2074 break;
2075 }
2076 return Handle<Code>::null();
2077 }
2078
2079
2080 #undef TRACE_IC 1991 #undef TRACE_IC
2081 1992
2082 1993
2083 // ---------------------------------------------------------------------------- 1994 // ----------------------------------------------------------------------------
2084 // Static IC stub generators. 1995 // Static IC stub generators.
2085 // 1996 //
2086 1997
2087 // Used from ic-<arch>.cc. 1998 // Used from ic-<arch>.cc.
2088 RUNTIME_FUNCTION(MaybeObject*, CallIC_Miss) { 1999 RUNTIME_FUNCTION(MaybeObject*, CallIC_Miss) {
2089 HandleScope scope(isolate); 2000 HandleScope scope(isolate);
(...skipping 712 matching lines...) Expand 10 before | Expand all | Expand 10 after
2802 #undef ADDR 2713 #undef ADDR
2803 }; 2714 };
2804 2715
2805 2716
2806 Address IC::AddressFromUtilityId(IC::UtilityId id) { 2717 Address IC::AddressFromUtilityId(IC::UtilityId id) {
2807 return IC_utilities[id]; 2718 return IC_utilities[id];
2808 } 2719 }
2809 2720
2810 2721
2811 } } // namespace v8::internal 2722 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698