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

Unified Diff: src/ic/ic.cc

Issue 541723002: Use a switch over it-state to compiler handlers (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 3 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/ic/ic.cc
diff --git a/src/ic/ic.cc b/src/ic/ic.cc
index a2d60143028bbb0c0fb72147111b4582a3c059aa..1c6e72be23935282f17ad03d233c2ca5e61cefff 100644
--- a/src/ic/ic.cc
+++ b/src/ic/ic.cc
@@ -963,120 +963,130 @@ Handle<Code> LoadIC::CompileHandler(LookupIterator* lookup,
Handle<HeapType> type = receiver_type();
Handle<JSObject> holder = lookup->GetHolder<JSObject>();
bool receiver_is_holder = receiver.is_identical_to(holder);
- // -------------- Interceptors --------------
- if (lookup->state() == LookupIterator::INTERCEPTOR) {
- DCHECK(!holder->GetNamedInterceptor()->getter()->IsUndefined());
- NamedLoadHandlerCompiler compiler(isolate(), receiver_type(), holder,
- cache_holder);
- // Perform a lookup behind the interceptor. Copy the LookupIterator since
- // the original iterator will be used to fetch the value.
- LookupIterator it = *lookup;
- it.Next();
- LookupForRead(&it);
- return compiler.CompileLoadInterceptor(&it);
- }
-
- // -------------- Accessors --------------
- if (lookup->state() == LookupIterator::ACCESSOR) {
- // Use simple field loads for some well-known callback properties.
- if (receiver_is_holder) {
- DCHECK(receiver->IsJSObject());
- Handle<JSObject> js_receiver = Handle<JSObject>::cast(receiver);
- int object_offset;
- if (Accessors::IsJSObjectFieldAccessor<HeapType>(type, lookup->name(),
- &object_offset)) {
- FieldIndex index =
- FieldIndex::ForInObjectOffset(object_offset, js_receiver->map());
- return SimpleFieldLoad(index);
- }
- }
-
- Handle<Object> accessors = lookup->GetAccessors();
- if (accessors->IsExecutableAccessorInfo()) {
- Handle<ExecutableAccessorInfo> info =
- Handle<ExecutableAccessorInfo>::cast(accessors);
- if (v8::ToCData<Address>(info->getter()) == 0) return slow_stub();
- if (!ExecutableAccessorInfo::IsCompatibleReceiverType(isolate(), info,
- type)) {
- return slow_stub();
- }
- if (!holder->HasFastProperties()) return slow_stub();
+ switch (lookup->state()) {
+ case LookupIterator::INTERCEPTOR: {
+ DCHECK(!holder->GetNamedInterceptor()->getter()->IsUndefined());
NamedLoadHandlerCompiler compiler(isolate(), receiver_type(), holder,
cache_holder);
- return compiler.CompileLoadCallback(lookup->name(), info);
+ // Perform a lookup behind the interceptor. Copy the LookupIterator since
+ // the original iterator will be used to fetch the value.
+ LookupIterator it = *lookup;
+ it.Next();
+ LookupForRead(&it);
+ return compiler.CompileLoadInterceptor(&it);
}
- if (accessors->IsAccessorPair()) {
- Handle<Object> getter(Handle<AccessorPair>::cast(accessors)->getter(),
- isolate());
- if (!getter->IsJSFunction()) return slow_stub();
- if (!holder->HasFastProperties()) return slow_stub();
- Handle<JSFunction> function = Handle<JSFunction>::cast(getter);
- if (!receiver->IsJSObject() && !function->IsBuiltin() &&
- function->shared()->strict_mode() == SLOPPY) {
- // Calling sloppy non-builtins with a value as the receiver
- // requires boxing.
- return slow_stub();
+
+ case LookupIterator::ACCESSOR: {
+ // Use simple field loads for some well-known callback properties.
+ if (receiver_is_holder) {
+ DCHECK(receiver->IsJSObject());
+ Handle<JSObject> js_receiver = Handle<JSObject>::cast(receiver);
+ int object_offset;
+ if (Accessors::IsJSObjectFieldAccessor<HeapType>(type, lookup->name(),
+ &object_offset)) {
+ FieldIndex index =
+ FieldIndex::ForInObjectOffset(object_offset, js_receiver->map());
+ return SimpleFieldLoad(index);
+ }
}
- CallOptimization call_optimization(function);
- NamedLoadHandlerCompiler compiler(isolate(), receiver_type(), holder,
- cache_holder);
- if (call_optimization.is_simple_api_call() &&
- call_optimization.IsCompatibleReceiver(receiver, holder)) {
- return compiler.CompileLoadCallback(lookup->name(), call_optimization);
+
+ Handle<Object> accessors = lookup->GetAccessors();
+ if (accessors->IsExecutableAccessorInfo()) {
+ Handle<ExecutableAccessorInfo> info =
+ Handle<ExecutableAccessorInfo>::cast(accessors);
+ if (v8::ToCData<Address>(info->getter()) == 0) break;
+ if (!ExecutableAccessorInfo::IsCompatibleReceiverType(isolate(), info,
+ type)) {
+ break;
+ }
+ if (!holder->HasFastProperties()) break;
+ NamedLoadHandlerCompiler compiler(isolate(), receiver_type(), holder,
+ cache_holder);
+ return compiler.CompileLoadCallback(lookup->name(), info);
}
- return compiler.CompileLoadViaGetter(lookup->name(), function);
+ if (accessors->IsAccessorPair()) {
+ Handle<Object> getter(Handle<AccessorPair>::cast(accessors)->getter(),
+ isolate());
+ if (!getter->IsJSFunction()) break;
+ if (!holder->HasFastProperties()) break;
+ Handle<JSFunction> function = Handle<JSFunction>::cast(getter);
+ if (!receiver->IsJSObject() && !function->IsBuiltin() &&
+ function->shared()->strict_mode() == SLOPPY) {
+ // Calling sloppy non-builtins with a value as the receiver
+ // requires boxing.
+ break;
+ }
+ CallOptimization call_optimization(function);
+ NamedLoadHandlerCompiler compiler(isolate(), receiver_type(), holder,
+ cache_holder);
+ if (call_optimization.is_simple_api_call() &&
+ call_optimization.IsCompatibleReceiver(receiver, holder)) {
+ return compiler.CompileLoadCallback(lookup->name(),
+ call_optimization);
+ }
+ return compiler.CompileLoadViaGetter(lookup->name(), function);
+ }
+ // TODO(dcarney): Handle correctly.
+ DCHECK(accessors->IsDeclaredAccessorInfo());
+ break;
}
- // TODO(dcarney): Handle correctly.
- DCHECK(accessors->IsDeclaredAccessorInfo());
- return slow_stub();
- }
- // -------------- Dictionary properties --------------
- DCHECK(lookup->state() == LookupIterator::DATA);
- if (lookup->is_dictionary_holder()) {
- if (kind() != Code::LOAD_IC) return slow_stub();
- if (holder->IsGlobalObject()) {
+ case LookupIterator::DATA: {
+ if (lookup->is_dictionary_holder()) {
+ if (kind() != Code::LOAD_IC) break;
+ if (holder->IsGlobalObject()) {
+ NamedLoadHandlerCompiler compiler(isolate(), receiver_type(), holder,
+ cache_holder);
+ Handle<PropertyCell> cell = lookup->GetPropertyCell();
+ Handle<Code> code = compiler.CompileLoadGlobal(
+ cell, lookup->name(), lookup->IsConfigurable());
+ // TODO(verwaest): Move caching of these NORMAL stubs outside as well.
+ CacheHolderFlag flag;
+ Handle<Map> stub_holder_map = GetHandlerCacheHolder(
+ *type, receiver_is_holder, isolate(), &flag);
+ Map::UpdateCodeCache(stub_holder_map, lookup->name(), code);
+ return code;
+ }
+ // There is only one shared stub for loading normalized
+ // properties. It does not traverse the prototype chain, so the
+ // property must be found in the object for the stub to be
+ // applicable.
+ if (!receiver_is_holder) break;
+ return isolate()->builtins()->LoadIC_Normal();
+ }
+
+ // -------------- Fields --------------
+ if (lookup->property_details().type() == FIELD) {
+ FieldIndex field = lookup->GetFieldIndex();
+ if (receiver_is_holder) {
+ return SimpleFieldLoad(field);
+ }
+ NamedLoadHandlerCompiler compiler(isolate(), receiver_type(), holder,
+ cache_holder);
+ return compiler.CompileLoadField(lookup->name(), field);
+ }
+
+ // -------------- Constant properties --------------
+ DCHECK(lookup->property_details().type() == CONSTANT);
+ if (receiver_is_holder) {
+ LoadConstantStub stub(isolate(), lookup->GetConstantIndex());
+ return stub.GetCode();
+ }
NamedLoadHandlerCompiler compiler(isolate(), receiver_type(), holder,
cache_holder);
- Handle<PropertyCell> cell = lookup->GetPropertyCell();
- Handle<Code> code = compiler.CompileLoadGlobal(cell, lookup->name(),
- lookup->IsConfigurable());
- // TODO(verwaest): Move caching of these NORMAL stubs outside as well.
- CacheHolderFlag flag;
- Handle<Map> stub_holder_map =
- GetHandlerCacheHolder(*type, receiver_is_holder, isolate(), &flag);
- Map::UpdateCodeCache(stub_holder_map, lookup->name(), code);
- return code;
+ return compiler.CompileLoadConstant(lookup->name(),
+ lookup->GetConstantIndex());
}
- // There is only one shared stub for loading normalized
- // properties. It does not traverse the prototype chain, so the
- // property must be found in the object for the stub to be
- // applicable.
- if (!receiver_is_holder) return slow_stub();
- return isolate()->builtins()->LoadIC_Normal();
- }
-
- // -------------- Fields --------------
- if (lookup->property_details().type() == FIELD) {
- FieldIndex field = lookup->GetFieldIndex();
- if (receiver_is_holder) {
- return SimpleFieldLoad(field);
- }
- NamedLoadHandlerCompiler compiler(isolate(), receiver_type(), holder,
- cache_holder);
- return compiler.CompileLoadField(lookup->name(), field);
- }
- // -------------- Constant properties --------------
- DCHECK(lookup->property_details().type() == CONSTANT);
- if (receiver_is_holder) {
- LoadConstantStub stub(isolate(), lookup->GetConstantIndex());
- return stub.GetCode();
+ case LookupIterator::ACCESS_CHECK:
+ case LookupIterator::JSPROXY:
+ case LookupIterator::NOT_FOUND:
+ case LookupIterator::TRANSITION:
+ case LookupIterator::UNKNOWN:
+ UNREACHABLE();
}
- NamedLoadHandlerCompiler compiler(isolate(), receiver_type(), holder,
- cache_holder);
- return compiler.CompileLoadConstant(lookup->name(),
- lookup->GetConstantIndex());
+
+ return slow_stub();
}
@@ -1400,96 +1410,102 @@ Handle<Code> StoreIC::CompileHandler(LookupIterator* lookup,
Handle<JSObject> holder = lookup->GetHolder<JSObject>();
DCHECK(!receiver->IsAccessCheckNeeded());
- // -------------- Transition --------------
- if (lookup->state() == LookupIterator::TRANSITION) {
- Handle<Map> transition = lookup->transition_map();
- // Currently not handled by CompileStoreTransition.
- if (!holder->HasFastProperties()) return slow_stub();
-
- DCHECK(lookup->IsCacheableTransition());
- NamedStoreHandlerCompiler compiler(isolate(), receiver_type(), holder);
- return compiler.CompileStoreTransition(transition, lookup->name());
- }
-
- // -------------- Interceptors --------------
- if (lookup->state() == LookupIterator::INTERCEPTOR) {
- DCHECK(!holder->GetNamedInterceptor()->setter()->IsUndefined());
- NamedStoreHandlerCompiler compiler(isolate(), receiver_type(), holder);
- return compiler.CompileStoreInterceptor(lookup->name());
- }
-
- // -------------- Accessors --------------
- if (lookup->state() == LookupIterator::ACCESSOR) {
- if (!holder->HasFastProperties()) return slow_stub();
- Handle<Object> accessors = lookup->GetAccessors();
- if (accessors->IsExecutableAccessorInfo()) {
- Handle<ExecutableAccessorInfo> info =
- Handle<ExecutableAccessorInfo>::cast(accessors);
- if (v8::ToCData<Address>(info->setter()) == 0) return slow_stub();
- if (!ExecutableAccessorInfo::IsCompatibleReceiverType(isolate(), info,
- receiver_type())) {
- return slow_stub();
- }
- NamedStoreHandlerCompiler compiler(isolate(), receiver_type(), holder);
- return compiler.CompileStoreCallback(receiver, lookup->name(), info);
- } else if (accessors->IsAccessorPair()) {
- Handle<Object> setter(Handle<AccessorPair>::cast(accessors)->setter(),
- isolate());
- if (!setter->IsJSFunction()) return slow_stub();
- Handle<JSFunction> function = Handle<JSFunction>::cast(setter);
- CallOptimization call_optimization(function);
+ switch (lookup->state()) {
+ case LookupIterator::TRANSITION: {
+ Handle<Map> transition = lookup->transition_map();
+ // Currently not handled by CompileStoreTransition.
+ if (!holder->HasFastProperties()) break;
+
+ DCHECK(lookup->IsCacheableTransition());
NamedStoreHandlerCompiler compiler(isolate(), receiver_type(), holder);
- if (call_optimization.is_simple_api_call() &&
- call_optimization.IsCompatibleReceiver(receiver, holder)) {
- return compiler.CompileStoreCallback(receiver, lookup->name(),
- call_optimization);
- }
- return compiler.CompileStoreViaSetter(receiver, lookup->name(),
- Handle<JSFunction>::cast(setter));
+ return compiler.CompileStoreTransition(transition, lookup->name());
}
- // TODO(dcarney): Handle correctly.
- DCHECK(accessors->IsDeclaredAccessorInfo());
- return slow_stub();
- }
-
- // -------------- Dictionary properties --------------
- DCHECK(lookup->state() == LookupIterator::DATA);
- if (lookup->is_dictionary_holder()) {
- if (holder->IsGlobalObject()) {
- Handle<PropertyCell> cell = lookup->GetPropertyCell();
- Handle<HeapType> union_type = PropertyCell::UpdatedType(cell, value);
- StoreGlobalStub stub(isolate(), union_type->IsConstant(),
- receiver->IsJSGlobalProxy());
- Handle<Code> code = stub.GetCodeCopyFromTemplate(
- Handle<GlobalObject>::cast(holder), cell);
- // TODO(verwaest): Move caching of these NORMAL stubs outside as well.
- HeapObject::UpdateMapCodeCache(receiver, lookup->name(), code);
- return code;
+
+ case LookupIterator::INTERCEPTOR: {
+ DCHECK(!holder->GetNamedInterceptor()->setter()->IsUndefined());
+ NamedStoreHandlerCompiler compiler(isolate(), receiver_type(), holder);
+ return compiler.CompileStoreInterceptor(lookup->name());
}
- DCHECK(holder.is_identical_to(receiver));
- return isolate()->builtins()->StoreIC_Normal();
- }
-
- // -------------- Fields --------------
- if (lookup->property_details().type() == FIELD) {
- bool use_stub = true;
- if (lookup->representation().IsHeapObject()) {
- // Only use a generic stub if no types need to be tracked.
- Handle<HeapType> field_type = lookup->GetFieldType();
- HeapType::Iterator<Map> it = field_type->Classes();
- use_stub = it.Done();
+
+ case LookupIterator::ACCESSOR: {
+ if (!holder->HasFastProperties()) break;
+ Handle<Object> accessors = lookup->GetAccessors();
+ if (accessors->IsExecutableAccessorInfo()) {
+ Handle<ExecutableAccessorInfo> info =
+ Handle<ExecutableAccessorInfo>::cast(accessors);
+ if (v8::ToCData<Address>(info->setter()) == 0) break;
+ if (!ExecutableAccessorInfo::IsCompatibleReceiverType(
+ isolate(), info, receiver_type())) {
+ break;
+ }
+ NamedStoreHandlerCompiler compiler(isolate(), receiver_type(), holder);
+ return compiler.CompileStoreCallback(receiver, lookup->name(), info);
+ } else if (accessors->IsAccessorPair()) {
+ Handle<Object> setter(Handle<AccessorPair>::cast(accessors)->setter(),
+ isolate());
+ if (!setter->IsJSFunction()) break;
+ Handle<JSFunction> function = Handle<JSFunction>::cast(setter);
+ CallOptimization call_optimization(function);
+ NamedStoreHandlerCompiler compiler(isolate(), receiver_type(), holder);
+ if (call_optimization.is_simple_api_call() &&
+ call_optimization.IsCompatibleReceiver(receiver, holder)) {
+ return compiler.CompileStoreCallback(receiver, lookup->name(),
+ call_optimization);
+ }
+ return compiler.CompileStoreViaSetter(receiver, lookup->name(),
+ Handle<JSFunction>::cast(setter));
+ }
+ // TODO(dcarney): Handle correctly.
+ DCHECK(accessors->IsDeclaredAccessorInfo());
+ break;
}
- if (use_stub) {
- StoreFieldStub stub(isolate(), lookup->GetFieldIndex(),
- lookup->representation());
- return stub.GetCode();
+
+ case LookupIterator::DATA: {
+ if (lookup->is_dictionary_holder()) {
+ if (holder->IsGlobalObject()) {
+ Handle<PropertyCell> cell = lookup->GetPropertyCell();
+ Handle<HeapType> union_type = PropertyCell::UpdatedType(cell, value);
+ StoreGlobalStub stub(isolate(), union_type->IsConstant(),
+ receiver->IsJSGlobalProxy());
+ Handle<Code> code = stub.GetCodeCopyFromTemplate(
+ Handle<GlobalObject>::cast(holder), cell);
+ // TODO(verwaest): Move caching of these NORMAL stubs outside as well.
+ HeapObject::UpdateMapCodeCache(receiver, lookup->name(), code);
+ return code;
+ }
+ DCHECK(holder.is_identical_to(receiver));
+ return isolate()->builtins()->StoreIC_Normal();
+ }
+
+ // -------------- Fields --------------
+ if (lookup->property_details().type() == FIELD) {
+ bool use_stub = true;
+ if (lookup->representation().IsHeapObject()) {
+ // Only use a generic stub if no types need to be tracked.
+ Handle<HeapType> field_type = lookup->GetFieldType();
+ HeapType::Iterator<Map> it = field_type->Classes();
+ use_stub = it.Done();
+ }
+ if (use_stub) {
+ StoreFieldStub stub(isolate(), lookup->GetFieldIndex(),
+ lookup->representation());
+ return stub.GetCode();
+ }
+ NamedStoreHandlerCompiler compiler(isolate(), receiver_type(), holder);
+ return compiler.CompileStoreField(lookup);
+ }
+
+ // -------------- Constant properties --------------
+ DCHECK(lookup->property_details().type() == CONSTANT);
+ break;
}
- NamedStoreHandlerCompiler compiler(isolate(), receiver_type(), holder);
- return compiler.CompileStoreField(lookup);
- }
- // -------------- Constant properties --------------
- DCHECK(lookup->property_details().type() == CONSTANT);
+ case LookupIterator::ACCESS_CHECK:
+ case LookupIterator::JSPROXY:
+ case LookupIterator::NOT_FOUND:
+ case LookupIterator::UNKNOWN:
+ UNREACHABLE();
+ }
return slow_stub();
}
« 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