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

Side by Side Diff: src/ic.cc

Issue 443993002: Only allocate a handler compiler when necessary (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 4 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 | no next file » | 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 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/v8.h" 5 #include "src/v8.h"
6 6
7 #include "src/accessors.h" 7 #include "src/accessors.h"
8 #include "src/api.h" 8 #include "src/api.h"
9 #include "src/arguments.h" 9 #include "src/arguments.h"
10 #include "src/codegen.h" 10 #include "src/codegen.h"
(...skipping 980 matching lines...) Expand 10 before | Expand all | Expand 10 after
991 Handle<JSFunction>::cast(object)->should_have_prototype() && 991 Handle<JSFunction>::cast(object)->should_have_prototype() &&
992 !Handle<JSFunction>::cast(object)->map()->has_non_instance_prototype()) { 992 !Handle<JSFunction>::cast(object)->map()->has_non_instance_prototype()) {
993 Handle<Code> stub; 993 Handle<Code> stub;
994 FunctionPrototypeStub function_prototype_stub(isolate()); 994 FunctionPrototypeStub function_prototype_stub(isolate());
995 return function_prototype_stub.GetCode(); 995 return function_prototype_stub.GetCode();
996 } 996 }
997 997
998 Handle<HeapType> type = receiver_type(); 998 Handle<HeapType> type = receiver_type();
999 Handle<JSObject> holder = lookup->GetHolder<JSObject>(); 999 Handle<JSObject> holder = lookup->GetHolder<JSObject>();
1000 bool receiver_is_holder = object.is_identical_to(holder); 1000 bool receiver_is_holder = object.is_identical_to(holder);
1001 NamedLoadHandlerCompiler compiler(isolate(), receiver_type(), holder,
1002 cache_holder);
1003
1004 // -------------- Interceptors -------------- 1001 // -------------- Interceptors --------------
1005 if (lookup->state() == LookupIterator::INTERCEPTOR) { 1002 if (lookup->state() == LookupIterator::INTERCEPTOR) {
1006 DCHECK(!holder->GetNamedInterceptor()->getter()->IsUndefined()); 1003 DCHECK(!holder->GetNamedInterceptor()->getter()->IsUndefined());
1004 NamedLoadHandlerCompiler compiler(isolate(), receiver_type(), holder,
1005 cache_holder);
1007 return compiler.CompileLoadInterceptor(name); 1006 return compiler.CompileLoadInterceptor(name);
1008 } 1007 }
1009 DCHECK(lookup->state() == LookupIterator::PROPERTY); 1008 DCHECK(lookup->state() == LookupIterator::PROPERTY);
1010 1009
1011 // -------------- Accessors -------------- 1010 // -------------- Accessors --------------
1012 if (lookup->property_kind() == LookupIterator::ACCESSOR) { 1011 if (lookup->property_kind() == LookupIterator::ACCESSOR) {
1013 // Use simple field loads for some well-known callback properties. 1012 // Use simple field loads for some well-known callback properties.
1014 if (receiver_is_holder) { 1013 if (receiver_is_holder) {
1015 DCHECK(object->IsJSObject()); 1014 DCHECK(object->IsJSObject());
1016 Handle<JSObject> receiver = Handle<JSObject>::cast(object); 1015 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1017 int object_offset; 1016 int object_offset;
1018 if (Accessors::IsJSObjectFieldAccessor<HeapType>(type, name, 1017 if (Accessors::IsJSObjectFieldAccessor<HeapType>(type, name,
1019 &object_offset)) { 1018 &object_offset)) {
1020 FieldIndex index = 1019 FieldIndex index =
1021 FieldIndex::ForInObjectOffset(object_offset, receiver->map()); 1020 FieldIndex::ForInObjectOffset(object_offset, receiver->map());
1022 return SimpleFieldLoad(index); 1021 return SimpleFieldLoad(index);
1023 } 1022 }
1024 } 1023 }
1025 1024
1026 Handle<Object> accessors = lookup->GetAccessors(); 1025 Handle<Object> accessors = lookup->GetAccessors();
1027 if (accessors->IsExecutableAccessorInfo()) { 1026 if (accessors->IsExecutableAccessorInfo()) {
1028 Handle<ExecutableAccessorInfo> info = 1027 Handle<ExecutableAccessorInfo> info =
1029 Handle<ExecutableAccessorInfo>::cast(accessors); 1028 Handle<ExecutableAccessorInfo>::cast(accessors);
1030 if (v8::ToCData<Address>(info->getter()) == 0) return slow_stub(); 1029 if (v8::ToCData<Address>(info->getter()) == 0) return slow_stub();
1031 if (!ExecutableAccessorInfo::IsCompatibleReceiverType(isolate(), info, 1030 if (!ExecutableAccessorInfo::IsCompatibleReceiverType(isolate(), info,
1032 type)) { 1031 type)) {
1033 return slow_stub(); 1032 return slow_stub();
1034 } 1033 }
1035 if (!holder->HasFastProperties()) return slow_stub(); 1034 if (!holder->HasFastProperties()) return slow_stub();
1035 NamedLoadHandlerCompiler compiler(isolate(), receiver_type(), holder,
1036 cache_holder);
1036 return compiler.CompileLoadCallback(name, info); 1037 return compiler.CompileLoadCallback(name, info);
1037 } 1038 }
1038 if (accessors->IsAccessorPair()) { 1039 if (accessors->IsAccessorPair()) {
1039 Handle<Object> getter(Handle<AccessorPair>::cast(accessors)->getter(), 1040 Handle<Object> getter(Handle<AccessorPair>::cast(accessors)->getter(),
1040 isolate()); 1041 isolate());
1041 if (!getter->IsJSFunction()) return slow_stub(); 1042 if (!getter->IsJSFunction()) return slow_stub();
1042 if (!holder->HasFastProperties()) return slow_stub(); 1043 if (!holder->HasFastProperties()) return slow_stub();
1043 Handle<JSFunction> function = Handle<JSFunction>::cast(getter); 1044 Handle<JSFunction> function = Handle<JSFunction>::cast(getter);
1044 if (!object->IsJSObject() && !function->IsBuiltin() && 1045 if (!object->IsJSObject() && !function->IsBuiltin() &&
1045 function->shared()->strict_mode() == SLOPPY) { 1046 function->shared()->strict_mode() == SLOPPY) {
1046 // Calling sloppy non-builtins with a value as the receiver 1047 // Calling sloppy non-builtins with a value as the receiver
1047 // requires boxing. 1048 // requires boxing.
1048 return slow_stub(); 1049 return slow_stub();
1049 } 1050 }
1050 CallOptimization call_optimization(function); 1051 CallOptimization call_optimization(function);
1052 NamedLoadHandlerCompiler compiler(isolate(), receiver_type(), holder,
1053 cache_holder);
1051 if (call_optimization.is_simple_api_call() && 1054 if (call_optimization.is_simple_api_call() &&
1052 call_optimization.IsCompatibleReceiver(object, holder)) { 1055 call_optimization.IsCompatibleReceiver(object, holder)) {
1053 return compiler.CompileLoadCallback(name, call_optimization); 1056 return compiler.CompileLoadCallback(name, call_optimization);
1054 } 1057 }
1055 return compiler.CompileLoadViaGetter(name, function); 1058 return compiler.CompileLoadViaGetter(name, function);
1056 } 1059 }
1057 // TODO(dcarney): Handle correctly. 1060 // TODO(dcarney): Handle correctly.
1058 DCHECK(accessors->IsDeclaredAccessorInfo()); 1061 DCHECK(accessors->IsDeclaredAccessorInfo());
1059 return slow_stub(); 1062 return slow_stub();
1060 } 1063 }
1061 1064
1062 // -------------- Dictionary properties -------------- 1065 // -------------- Dictionary properties --------------
1063 DCHECK(lookup->property_kind() == LookupIterator::DATA); 1066 DCHECK(lookup->property_kind() == LookupIterator::DATA);
1064 if (lookup->property_encoding() == LookupIterator::DICTIONARY) { 1067 if (lookup->property_encoding() == LookupIterator::DICTIONARY) {
1065 if (kind() != Code::LOAD_IC) return slow_stub(); 1068 if (kind() != Code::LOAD_IC) return slow_stub();
1066 if (holder->IsGlobalObject()) { 1069 if (holder->IsGlobalObject()) {
1070 NamedLoadHandlerCompiler compiler(isolate(), receiver_type(), holder,
1071 cache_holder);
1067 Handle<PropertyCell> cell = lookup->GetPropertyCell(); 1072 Handle<PropertyCell> cell = lookup->GetPropertyCell();
1068 Handle<Code> code = 1073 Handle<Code> code =
1069 compiler.CompileLoadGlobal(cell, name, lookup->IsConfigurable()); 1074 compiler.CompileLoadGlobal(cell, name, lookup->IsConfigurable());
1070 // TODO(verwaest): Move caching of these NORMAL stubs outside as well. 1075 // TODO(verwaest): Move caching of these NORMAL stubs outside as well.
1071 CacheHolderFlag flag; 1076 CacheHolderFlag flag;
1072 Handle<Map> stub_holder_map = 1077 Handle<Map> stub_holder_map =
1073 GetHandlerCacheHolder(*type, receiver_is_holder, isolate(), &flag); 1078 GetHandlerCacheHolder(*type, receiver_is_holder, isolate(), &flag);
1074 Map::UpdateCodeCache(stub_holder_map, name, code); 1079 Map::UpdateCodeCache(stub_holder_map, name, code);
1075 return code; 1080 return code;
1076 } 1081 }
1077 // There is only one shared stub for loading normalized 1082 // There is only one shared stub for loading normalized
1078 // properties. It does not traverse the prototype chain, so the 1083 // properties. It does not traverse the prototype chain, so the
1079 // property must be found in the object for the stub to be 1084 // property must be found in the object for the stub to be
1080 // applicable. 1085 // applicable.
1081 if (!receiver_is_holder) return slow_stub(); 1086 if (!receiver_is_holder) return slow_stub();
1082 return isolate()->builtins()->LoadIC_Normal(); 1087 return isolate()->builtins()->LoadIC_Normal();
1083 } 1088 }
1084 1089
1085 // -------------- Fields -------------- 1090 // -------------- Fields --------------
1086 DCHECK(lookup->property_encoding() == LookupIterator::DESCRIPTOR); 1091 DCHECK(lookup->property_encoding() == LookupIterator::DESCRIPTOR);
1087 if (lookup->property_details().type() == FIELD) { 1092 if (lookup->property_details().type() == FIELD) {
1088 FieldIndex field = lookup->GetFieldIndex(); 1093 FieldIndex field = lookup->GetFieldIndex();
1089 if (receiver_is_holder) { 1094 if (receiver_is_holder) {
1090 return SimpleFieldLoad(field); 1095 return SimpleFieldLoad(field);
1091 } 1096 }
1097 NamedLoadHandlerCompiler compiler(isolate(), receiver_type(), holder,
1098 cache_holder);
1092 return compiler.CompileLoadField(name, field); 1099 return compiler.CompileLoadField(name, field);
1093 } 1100 }
1094 1101
1095 // -------------- Constant properties -------------- 1102 // -------------- Constant properties --------------
1096 DCHECK(lookup->property_details().type() == CONSTANT); 1103 DCHECK(lookup->property_details().type() == CONSTANT);
1097 if (receiver_is_holder) { 1104 if (receiver_is_holder) {
1098 LoadConstantStub stub(isolate(), lookup->GetConstantIndex()); 1105 LoadConstantStub stub(isolate(), lookup->GetConstantIndex());
1099 return stub.GetCode(); 1106 return stub.GetCode();
1100 } 1107 }
1108 NamedLoadHandlerCompiler compiler(isolate(), receiver_type(), holder,
1109 cache_holder);
1101 return compiler.CompileLoadConstant(name, lookup->GetConstantIndex()); 1110 return compiler.CompileLoadConstant(name, lookup->GetConstantIndex());
1102 } 1111 }
1103 1112
1104 1113
1105 static Handle<Object> TryConvertKey(Handle<Object> key, Isolate* isolate) { 1114 static Handle<Object> TryConvertKey(Handle<Object> key, Isolate* isolate) {
1106 // This helper implements a few common fast cases for converting 1115 // This helper implements a few common fast cases for converting
1107 // non-smi keys of keyed loads/stores to a smi or a string. 1116 // non-smi keys of keyed loads/stores to a smi or a string.
1108 if (key->IsHeapNumber()) { 1117 if (key->IsHeapNumber()) {
1109 double value = Handle<HeapNumber>::cast(key)->value(); 1118 double value = Handle<HeapNumber>::cast(key)->value();
1110 if (std::isnan(value)) { 1119 if (std::isnan(value)) {
(...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after
1452 Handle<String> name, 1461 Handle<String> name,
1453 Handle<Object> value, 1462 Handle<Object> value,
1454 CacheHolderFlag cache_holder) { 1463 CacheHolderFlag cache_holder) {
1455 if (object->IsAccessCheckNeeded()) return slow_stub(); 1464 if (object->IsAccessCheckNeeded()) return slow_stub();
1456 DCHECK(cache_holder == kCacheOnReceiver || lookup->type() == CALLBACKS || 1465 DCHECK(cache_holder == kCacheOnReceiver || lookup->type() == CALLBACKS ||
1457 (object->IsJSGlobalProxy() && lookup->holder()->IsJSGlobalObject())); 1466 (object->IsJSGlobalProxy() && lookup->holder()->IsJSGlobalObject()));
1458 // This is currently guaranteed by checks in StoreIC::Store. 1467 // This is currently guaranteed by checks in StoreIC::Store.
1459 Handle<JSObject> receiver = Handle<JSObject>::cast(object); 1468 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1460 1469
1461 Handle<JSObject> holder(lookup->holder()); 1470 Handle<JSObject> holder(lookup->holder());
1462 NamedStoreHandlerCompiler compiler(isolate(), receiver_type(), holder);
1463 1471
1464 if (lookup->IsTransition()) { 1472 if (lookup->IsTransition()) {
1465 // Explicitly pass in the receiver map since LookupForWrite may have 1473 // Explicitly pass in the receiver map since LookupForWrite may have
1466 // stored something else than the receiver in the holder. 1474 // stored something else than the receiver in the holder.
1467 Handle<Map> transition(lookup->GetTransitionTarget()); 1475 Handle<Map> transition(lookup->GetTransitionTarget());
1468 PropertyDetails details = lookup->GetPropertyDetails(); 1476 PropertyDetails details = lookup->GetPropertyDetails();
1469 1477
1470 if (details.type() != CALLBACKS && details.attributes() == NONE && 1478 if (details.type() != CALLBACKS && details.attributes() == NONE &&
1471 holder->HasFastProperties()) { 1479 holder->HasFastProperties()) {
1480 NamedStoreHandlerCompiler compiler(isolate(), receiver_type(), holder);
1472 return compiler.CompileStoreTransition(transition, name); 1481 return compiler.CompileStoreTransition(transition, name);
1473 } 1482 }
1474 } else { 1483 } else {
1475 switch (lookup->type()) { 1484 switch (lookup->type()) {
1476 case FIELD: { 1485 case FIELD: {
1477 bool use_stub = true; 1486 bool use_stub = true;
1478 if (lookup->representation().IsHeapObject()) { 1487 if (lookup->representation().IsHeapObject()) {
1479 // Only use a generic stub if no types need to be tracked. 1488 // Only use a generic stub if no types need to be tracked.
1480 HeapType* field_type = lookup->GetFieldType(); 1489 HeapType* field_type = lookup->GetFieldType();
1481 HeapType::Iterator<Map> it = field_type->Classes(); 1490 HeapType::Iterator<Map> it = field_type->Classes();
1482 use_stub = it.Done(); 1491 use_stub = it.Done();
1483 } 1492 }
1484 if (use_stub) { 1493 if (use_stub) {
1485 StoreFieldStub stub(isolate(), lookup->GetFieldIndex(), 1494 StoreFieldStub stub(isolate(), lookup->GetFieldIndex(),
1486 lookup->representation()); 1495 lookup->representation());
1487 return stub.GetCode(); 1496 return stub.GetCode();
1488 } 1497 }
1498 NamedStoreHandlerCompiler compiler(isolate(), receiver_type(), holder);
1489 return compiler.CompileStoreField(lookup, name); 1499 return compiler.CompileStoreField(lookup, name);
1490 } 1500 }
1491 case NORMAL: 1501 case NORMAL:
1492 if (receiver->IsJSGlobalProxy() || receiver->IsGlobalObject()) { 1502 if (receiver->IsJSGlobalProxy() || receiver->IsGlobalObject()) {
1493 // The stub generated for the global object picks the value directly 1503 // The stub generated for the global object picks the value directly
1494 // from the property cell. So the property must be directly on the 1504 // from the property cell. So the property must be directly on the
1495 // global object. 1505 // global object.
1496 PrototypeIterator iter(isolate(), receiver); 1506 PrototypeIterator iter(isolate(), receiver);
1497 Handle<GlobalObject> global = 1507 Handle<GlobalObject> global =
1498 receiver->IsJSGlobalProxy() 1508 receiver->IsJSGlobalProxy()
(...skipping 15 matching lines...) Expand all
1514 Handle<Object> callback(lookup->GetCallbackObject(), isolate()); 1524 Handle<Object> callback(lookup->GetCallbackObject(), isolate());
1515 if (callback->IsExecutableAccessorInfo()) { 1525 if (callback->IsExecutableAccessorInfo()) {
1516 Handle<ExecutableAccessorInfo> info = 1526 Handle<ExecutableAccessorInfo> info =
1517 Handle<ExecutableAccessorInfo>::cast(callback); 1527 Handle<ExecutableAccessorInfo>::cast(callback);
1518 if (v8::ToCData<Address>(info->setter()) == 0) break; 1528 if (v8::ToCData<Address>(info->setter()) == 0) break;
1519 if (!holder->HasFastProperties()) break; 1529 if (!holder->HasFastProperties()) break;
1520 if (!ExecutableAccessorInfo::IsCompatibleReceiverType( 1530 if (!ExecutableAccessorInfo::IsCompatibleReceiverType(
1521 isolate(), info, receiver_type())) { 1531 isolate(), info, receiver_type())) {
1522 break; 1532 break;
1523 } 1533 }
1534 NamedStoreHandlerCompiler compiler(isolate(), receiver_type(),
1535 holder);
1524 return compiler.CompileStoreCallback(receiver, name, info); 1536 return compiler.CompileStoreCallback(receiver, name, info);
1525 } else if (callback->IsAccessorPair()) { 1537 } else if (callback->IsAccessorPair()) {
1526 Handle<Object> setter( 1538 Handle<Object> setter(
1527 Handle<AccessorPair>::cast(callback)->setter(), isolate()); 1539 Handle<AccessorPair>::cast(callback)->setter(), isolate());
1528 if (!setter->IsJSFunction()) break; 1540 if (!setter->IsJSFunction()) break;
1529 if (holder->IsGlobalObject()) break; 1541 if (holder->IsGlobalObject()) break;
1530 if (!holder->HasFastProperties()) break; 1542 if (!holder->HasFastProperties()) break;
1531 Handle<JSFunction> function = Handle<JSFunction>::cast(setter); 1543 Handle<JSFunction> function = Handle<JSFunction>::cast(setter);
1532 CallOptimization call_optimization(function); 1544 CallOptimization call_optimization(function);
1545 NamedStoreHandlerCompiler compiler(isolate(), receiver_type(),
1546 holder);
1533 if (call_optimization.is_simple_api_call() && 1547 if (call_optimization.is_simple_api_call() &&
1534 call_optimization.IsCompatibleReceiver(receiver, holder)) { 1548 call_optimization.IsCompatibleReceiver(receiver, holder)) {
1535 return compiler.CompileStoreCallback(receiver, name, 1549 return compiler.CompileStoreCallback(receiver, name,
1536 call_optimization); 1550 call_optimization);
1537 } 1551 }
1538 return compiler.CompileStoreViaSetter( 1552 return compiler.CompileStoreViaSetter(
1539 receiver, name, Handle<JSFunction>::cast(setter)); 1553 receiver, name, Handle<JSFunction>::cast(setter));
1540 } 1554 }
1541 // TODO(dcarney): Handle correctly. 1555 // TODO(dcarney): Handle correctly.
1542 DCHECK(callback->IsDeclaredAccessorInfo()); 1556 DCHECK(callback->IsDeclaredAccessorInfo());
1543 break; 1557 break;
1544 } 1558 }
1545 case INTERCEPTOR: 1559 case INTERCEPTOR: {
1546 DCHECK(HasInterceptorSetter(*holder)); 1560 DCHECK(HasInterceptorSetter(*holder));
1561 NamedStoreHandlerCompiler compiler(isolate(), receiver_type(), holder);
1547 return compiler.CompileStoreInterceptor(name); 1562 return compiler.CompileStoreInterceptor(name);
1563 }
1548 case CONSTANT: 1564 case CONSTANT:
1549 break; 1565 break;
1550 case NONEXISTENT: 1566 case NONEXISTENT:
1551 case HANDLER: 1567 case HANDLER:
1552 UNREACHABLE(); 1568 UNREACHABLE();
1553 break; 1569 break;
1554 } 1570 }
1555 } 1571 }
1556 return slow_stub(); 1572 return slow_stub();
1557 } 1573 }
(...skipping 1547 matching lines...) Expand 10 before | Expand all | Expand 10 after
3105 #undef ADDR 3121 #undef ADDR
3106 }; 3122 };
3107 3123
3108 3124
3109 Address IC::AddressFromUtilityId(IC::UtilityId id) { 3125 Address IC::AddressFromUtilityId(IC::UtilityId id) {
3110 return IC_utilities[id]; 3126 return IC_utilities[id];
3111 } 3127 }
3112 3128
3113 3129
3114 } } // namespace v8::internal 3130 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698