summaryrefslogtreecommitdiff
path: root/deps/v8/src/ic/handler-compiler.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/ic/handler-compiler.cc')
-rw-r--r--deps/v8/src/ic/handler-compiler.cc320
1 files changed, 18 insertions, 302 deletions
diff --git a/deps/v8/src/ic/handler-compiler.cc b/deps/v8/src/ic/handler-compiler.cc
index 05e9031915..16aec0b494 100644
--- a/deps/v8/src/ic/handler-compiler.cc
+++ b/deps/v8/src/ic/handler-compiler.cc
@@ -24,60 +24,6 @@ Handle<Code> PropertyHandlerCompiler::Find(Handle<Name> name,
return handle(code);
}
-
-Handle<Code> NamedLoadHandlerCompiler::ComputeLoadNonexistent(
- Handle<Name> name, Handle<Map> receiver_map) {
- Isolate* isolate = name->GetIsolate();
- if (receiver_map->prototype()->IsNull(isolate)) {
- // TODO(jkummerow/verwaest): If there is no prototype and the property
- // is nonexistent, introduce a builtin to handle this (fast properties
- // -> return undefined, dictionary properties -> do negative lookup).
- return Handle<Code>();
- }
- CacheHolderFlag flag;
- Handle<Map> stub_holder_map =
- IC::GetHandlerCacheHolder(receiver_map, false, isolate, &flag);
-
- // If no dictionary mode objects are present in the prototype chain, the load
- // nonexistent IC stub can be shared for all names for a given map and we use
- // the empty string for the map cache in that case. If there are dictionary
- // mode objects involved, we need to do negative lookups in the stub and
- // therefore the stub will be specific to the name.
- Handle<Name> cache_name =
- receiver_map->is_dictionary_map()
- ? name
- : Handle<Name>::cast(isolate->factory()->nonexistent_symbol());
- Handle<Map> current_map = stub_holder_map;
- Handle<JSObject> last(JSObject::cast(receiver_map->prototype()));
- while (true) {
- if (current_map->is_dictionary_map()) cache_name = name;
- if (current_map->prototype()->IsNull(isolate)) break;
- if (name->IsPrivate()) {
- // TODO(verwaest): Use nonexistent_private_symbol.
- cache_name = name;
- if (!current_map->has_hidden_prototype()) break;
- }
-
- last = handle(JSObject::cast(current_map->prototype()));
- current_map = handle(last->map());
- }
- // Compile the stub that is either shared for all names or
- // name specific if there are global objects involved.
- Handle<Code> handler = PropertyHandlerCompiler::Find(
- cache_name, stub_holder_map, Code::LOAD_IC, flag);
- if (!handler.is_null()) {
- TRACE_HANDLER_STATS(isolate, LoadIC_HandlerCacheHit_NonExistent);
- return handler;
- }
-
- TRACE_HANDLER_STATS(isolate, LoadIC_LoadNonexistent);
- NamedLoadHandlerCompiler compiler(isolate, receiver_map, last, flag);
- handler = compiler.CompileLoadNonexistent(cache_name);
- Map::UpdateCodeCache(stub_holder_map, cache_name, handler);
- return handler;
-}
-
-
Handle<Code> PropertyHandlerCompiler::GetCode(Code::Kind kind,
Handle<Name> name) {
Code::Flags flags = Code::ComputeHandlerFlags(kind, cache_holder());
@@ -149,87 +95,6 @@ Register PropertyHandlerCompiler::Frontend(Handle<Name> name) {
return reg;
}
-
-void PropertyHandlerCompiler::NonexistentFrontendHeader(Handle<Name> name,
- Label* miss,
- Register scratch1,
- Register scratch2) {
- Register holder_reg;
- Handle<Map> last_map;
- if (holder().is_null()) {
- holder_reg = receiver();
- last_map = map();
- // If |type| has null as its prototype, |holder()| is
- // Handle<JSObject>::null().
- DCHECK(last_map->prototype() == isolate()->heap()->null_value());
- } else {
- last_map = handle(holder()->map());
- // This condition matches the branches below.
- bool need_holder =
- last_map->is_dictionary_map() && !last_map->IsJSGlobalObjectMap();
- holder_reg =
- FrontendHeader(receiver(), name, miss,
- need_holder ? RETURN_HOLDER : DONT_RETURN_ANYTHING);
- }
-
- if (last_map->is_dictionary_map()) {
- if (last_map->IsJSGlobalObjectMap()) {
- Handle<JSGlobalObject> global =
- holder().is_null()
- ? Handle<JSGlobalObject>::cast(isolate()->global_object())
- : Handle<JSGlobalObject>::cast(holder());
- GenerateCheckPropertyCell(masm(), global, name, scratch1, miss);
- } else {
- if (!name->IsUniqueName()) {
- DCHECK(name->IsString());
- name = factory()->InternalizeString(Handle<String>::cast(name));
- }
- DCHECK(holder().is_null() ||
- holder()->property_dictionary()->FindEntry(name) ==
- NameDictionary::kNotFound);
- GenerateDictionaryNegativeLookup(masm(), miss, holder_reg, name, scratch1,
- scratch2);
- }
- }
-}
-
-
-Handle<Code> NamedLoadHandlerCompiler::CompileLoadField(Handle<Name> name,
- FieldIndex field) {
- Register reg = Frontend(name);
- __ Move(receiver(), reg);
- LoadFieldStub stub(isolate(), field);
- GenerateTailCall(masm(), stub.GetCode());
- return GetCode(kind(), name);
-}
-
-
-Handle<Code> NamedLoadHandlerCompiler::CompileLoadConstant(Handle<Name> name,
- int constant_index) {
- Register reg = Frontend(name);
- __ Move(receiver(), reg);
- LoadConstantStub stub(isolate(), constant_index);
- GenerateTailCall(masm(), stub.GetCode());
- return GetCode(kind(), name);
-}
-
-
-Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent(
- Handle<Name> name) {
- Label miss;
- if (IC::ShouldPushPopSlotAndVector(kind())) {
- DCHECK(kind() == Code::LOAD_IC);
- PushVectorAndSlot();
- }
- NonexistentFrontendHeader(name, &miss, scratch2(), scratch3());
- if (IC::ShouldPushPopSlotAndVector(kind())) {
- DiscardVectorAndSlot();
- }
- GenerateLoadConstant(isolate()->factory()->undefined_value());
- FrontendFooter(name, &miss);
- return GetCode(kind(), name);
-}
-
Handle<Code> NamedLoadHandlerCompiler::CompileLoadCallback(
Handle<Name> name, Handle<AccessorInfo> callback, Handle<Code> slow_stub) {
if (V8_UNLIKELY(FLAG_runtime_stats)) {
@@ -298,10 +163,13 @@ Handle<Code> NamedLoadHandlerCompiler::CompileLoadInterceptor(
case LookupIterator::NOT_FOUND:
case LookupIterator::INTEGER_INDEXED_EXOTIC:
break;
- case LookupIterator::DATA:
- inline_followup =
- it->property_details().type() == DATA && !it->is_dictionary_holder();
+ case LookupIterator::DATA: {
+ PropertyDetails details = it->property_details();
+ inline_followup = details.kind() == kData &&
+ details.location() == kField &&
+ !it->is_dictionary_holder();
break;
+ }
case LookupIterator::ACCESSOR: {
Handle<Object> accessors = it->GetAccessors();
if (accessors->IsAccessorInfo()) {
@@ -409,9 +277,13 @@ void NamedLoadHandlerCompiler::GenerateLoadPostInterceptor(
case LookupIterator::TRANSITION:
UNREACHABLE();
case LookupIterator::DATA: {
- DCHECK_EQ(DATA, it->property_details().type());
- __ Move(receiver(), reg);
- LoadFieldStub stub(isolate(), it->GetFieldIndex());
+ DCHECK_EQ(kData, it->property_details().kind());
+ DCHECK_EQ(kField, it->property_details().location());
+ __ Move(LoadFieldDescriptor::ReceiverRegister(), reg);
+ Handle<Object> smi_handler =
+ LoadIC::SimpleFieldLoad(isolate(), it->GetFieldIndex());
+ __ Move(LoadFieldDescriptor::SmiHandlerRegister(), smi_handler);
+ LoadFieldStub stub(isolate());
GenerateTailCall(masm(), stub.GetCode());
break;
}
@@ -440,150 +312,6 @@ Handle<Code> NamedLoadHandlerCompiler::CompileLoadViaGetter(
return GetCode(kind(), name);
}
-
-// TODO(verwaest): Cleanup. holder() is actually the receiver.
-Handle<Code> NamedStoreHandlerCompiler::CompileStoreTransition(
- Handle<Map> transition, Handle<Name> name) {
- Label miss;
-
- // Ensure that the StoreTransitionStub we are going to call has the same
- // number of stack arguments. This means that we don't have to adapt them
- // if we decide to call the transition or miss stub.
- STATIC_ASSERT(Descriptor::kStackArgumentsCount ==
- StoreTransitionDescriptor::kStackArgumentsCount);
- STATIC_ASSERT(Descriptor::kStackArgumentsCount == 0 ||
- Descriptor::kStackArgumentsCount == 3);
- STATIC_ASSERT(Descriptor::kParameterCount - Descriptor::kValue ==
- StoreTransitionDescriptor::kParameterCount -
- StoreTransitionDescriptor::kValue);
- STATIC_ASSERT(Descriptor::kParameterCount - Descriptor::kSlot ==
- StoreTransitionDescriptor::kParameterCount -
- StoreTransitionDescriptor::kSlot);
- STATIC_ASSERT(Descriptor::kParameterCount - Descriptor::kVector ==
- StoreTransitionDescriptor::kParameterCount -
- StoreTransitionDescriptor::kVector);
-
- if (Descriptor::kPassLastArgsOnStack) {
- __ LoadParameterFromStack<Descriptor>(value(), Descriptor::kValue);
- }
-
- bool need_save_restore = IC::ShouldPushPopSlotAndVector(kind());
- if (need_save_restore) {
- PushVectorAndSlot();
- }
-
- // Check that we are allowed to write this.
- bool is_nonexistent = holder()->map() == transition->GetBackPointer();
- if (is_nonexistent) {
- // Find the top object.
- Handle<JSObject> last;
- PrototypeIterator::WhereToEnd end =
- name->IsPrivate() ? PrototypeIterator::END_AT_NON_HIDDEN
- : PrototypeIterator::END_AT_NULL;
- PrototypeIterator iter(isolate(), holder(), kStartAtPrototype, end);
- while (!iter.IsAtEnd()) {
- last = PrototypeIterator::GetCurrent<JSObject>(iter);
- iter.Advance();
- }
- if (!last.is_null()) set_holder(last);
- NonexistentFrontendHeader(name, &miss, scratch1(), scratch2());
- } else {
- FrontendHeader(receiver(), name, &miss, DONT_RETURN_ANYTHING);
- DCHECK(holder()->HasFastProperties());
- }
-
- int descriptor = transition->LastAdded();
- Handle<DescriptorArray> descriptors(transition->instance_descriptors());
- PropertyDetails details = descriptors->GetDetails(descriptor);
- Representation representation = details.representation();
- DCHECK(!representation.IsNone());
-
- // Stub is never generated for objects that require access checks.
- DCHECK(!transition->is_access_check_needed());
-
- // Call to respective StoreTransitionStub.
- Register map_reg = StoreTransitionDescriptor::MapRegister();
-
- if (details.type() == DATA_CONSTANT) {
- DCHECK(descriptors->GetValue(descriptor)->IsJSFunction());
- GenerateRestoreMap(transition, map_reg, scratch1(), &miss);
- GenerateConstantCheck(map_reg, descriptor, value(), scratch1(), &miss);
- if (need_save_restore) {
- PopVectorAndSlot();
- }
- GenerateRestoreName(name);
- StoreMapStub stub(isolate());
- GenerateTailCall(masm(), stub.GetCode());
-
- } else {
- if (representation.IsHeapObject()) {
- GenerateFieldTypeChecks(descriptors->GetFieldType(descriptor), value(),
- &miss);
- }
- StoreTransitionStub::StoreMode store_mode =
- Map::cast(transition->GetBackPointer())->unused_property_fields() == 0
- ? StoreTransitionStub::ExtendStorageAndStoreMapAndValue
- : StoreTransitionStub::StoreMapAndValue;
- GenerateRestoreMap(transition, map_reg, scratch1(), &miss);
- if (need_save_restore) {
- PopVectorAndSlot();
- }
- // We need to pass name on the stack.
- PopReturnAddress(this->name());
- __ Push(name);
- PushReturnAddress(this->name());
-
- FieldIndex index = FieldIndex::ForDescriptor(*transition, descriptor);
- __ Move(StoreNamedTransitionDescriptor::FieldOffsetRegister(),
- Smi::FromInt(index.index() << kPointerSizeLog2));
-
- StoreTransitionStub stub(isolate(), index.is_inobject(), representation,
- store_mode);
- GenerateTailCall(masm(), stub.GetCode());
- }
-
- __ bind(&miss);
- if (need_save_restore) {
- PopVectorAndSlot();
- }
- GenerateRestoreName(name);
- TailCallBuiltin(masm(), MissBuiltin(kind()));
-
- return GetCode(kind(), name);
-}
-
-bool NamedStoreHandlerCompiler::RequiresFieldTypeChecks(
- FieldType* field_type) const {
- return field_type->IsClass();
-}
-
-
-Handle<Code> NamedStoreHandlerCompiler::CompileStoreField(LookupIterator* it) {
- Label miss;
- DCHECK(it->representation().IsHeapObject());
-
- FieldType* field_type = *it->GetFieldType();
- bool need_save_restore = false;
- if (RequiresFieldTypeChecks(field_type)) {
- need_save_restore = IC::ShouldPushPopSlotAndVector(kind());
- if (Descriptor::kPassLastArgsOnStack) {
- __ LoadParameterFromStack<Descriptor>(value(), Descriptor::kValue);
- }
- if (need_save_restore) PushVectorAndSlot();
- GenerateFieldTypeChecks(field_type, value(), &miss);
- if (need_save_restore) PopVectorAndSlot();
- }
-
- StoreFieldStub stub(isolate(), it->GetFieldIndex(), it->representation());
- GenerateTailCall(masm(), stub.GetCode());
-
- __ bind(&miss);
- if (need_save_restore) PopVectorAndSlot();
- TailCallBuiltin(masm(), MissBuiltin(kind()));
- return GetCode(kind(), it->name());
-}
-
-
Handle<Code> NamedStoreHandlerCompiler::CompileStoreViaSetter(
Handle<JSObject> object, Handle<Name> name, int accessor_index,
int expected_arguments) {
@@ -640,13 +368,8 @@ Handle<Object> ElementHandlerCompiler::GetKeyedLoadHandler(
}
bool is_js_array = instance_type == JS_ARRAY_TYPE;
if (elements_kind == DICTIONARY_ELEMENTS) {
- if (FLAG_tf_load_ic_stub) {
- TRACE_HANDLER_STATS(isolate, KeyedLoadIC_LoadElementDH);
- return LoadHandler::LoadElement(isolate, elements_kind, false,
- is_js_array);
- }
- TRACE_HANDLER_STATS(isolate, KeyedLoadIC_LoadDictionaryElementStub);
- return LoadDictionaryElementStub(isolate).GetCode();
+ TRACE_HANDLER_STATS(isolate, KeyedLoadIC_LoadElementDH);
+ return LoadHandler::LoadElement(isolate, elements_kind, false, is_js_array);
}
DCHECK(IsFastElementsKind(elements_kind) ||
IsFixedTypedArrayElementsKind(elements_kind));
@@ -654,16 +377,9 @@ Handle<Object> ElementHandlerCompiler::GetKeyedLoadHandler(
bool convert_hole_to_undefined =
is_js_array && elements_kind == FAST_HOLEY_ELEMENTS &&
*receiver_map == isolate->get_initial_js_array_map(elements_kind);
- if (FLAG_tf_load_ic_stub) {
- TRACE_HANDLER_STATS(isolate, KeyedLoadIC_LoadElementDH);
- return LoadHandler::LoadElement(isolate, elements_kind,
- convert_hole_to_undefined, is_js_array);
- } else {
- TRACE_HANDLER_STATS(isolate, KeyedLoadIC_LoadFastElementStub);
- return LoadFastElementStub(isolate, is_js_array, elements_kind,
- convert_hole_to_undefined)
- .GetCode();
- }
+ TRACE_HANDLER_STATS(isolate, KeyedLoadIC_LoadElementDH);
+ return LoadHandler::LoadElement(isolate, elements_kind,
+ convert_hole_to_undefined, is_js_array);
}
void ElementHandlerCompiler::CompileElementHandlers(