Commit 13206667 authored by Benedikt Meurer's avatar Benedikt Meurer Committed by Commit Bot

[cleanup] Handle JSFunction::prototype and string length in CallGetterIfAccessor.

Also add support for JSFunction::prototype and JSString::length
accessors to CodeStubAssembler::CallGetterIfAccessor and remove
the special case hack from the LoadIC_Uninitialized.

Also address the TODO to unify the implementation with the
LoadIC_FunctionPrototype handler.

BUG=v8:5269,v8:6325
R=ishell@chromium.org

Change-Id: Ic51221e35a051c403d3a86dc41213c913e8f9d85
Reviewed-on: https://chromium-review.googlesource.com/489946
Commit-Queue: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: 's avatarIgor Sheludko <ishell@chromium.org>
Cr-Commit-Position: refs/heads/master@{#44964}
parent 32124f3b
......@@ -129,21 +129,8 @@ TF_BUILTIN(LoadIC_FunctionPrototype, CodeStubAssembler) {
Node* vector = Parameter(Descriptor::kVector);
Node* context = Parameter(Descriptor::kContext);
Label miss(this);
Node* proto_or_map =
LoadObjectField(receiver, JSFunction::kPrototypeOrInitialMapOffset);
GotoIf(IsTheHole(proto_or_map), &miss);
VARIABLE(var_result, MachineRepresentation::kTagged, proto_or_map);
Label done(this, &var_result);
GotoIfNot(IsMap(proto_or_map), &done);
var_result.Bind(LoadMapPrototype(proto_or_map));
Goto(&done);
BIND(&done);
Return(var_result.value());
Label miss(this, Label::kDeferred);
Return(LoadJSFunctionPrototype(receiver, &miss));
BIND(&miss);
TailCallRuntime(Runtime::kLoadIC_Miss, context, receiver, name, slot, vector);
......
......@@ -1430,6 +1430,27 @@ Node* CodeStubAssembler::LoadJSArrayElementsMap(ElementsKind kind,
return LoadContextElement(native_context, Context::ArrayMapIndex(kind));
}
Node* CodeStubAssembler::LoadJSFunctionPrototype(Node* function,
Label* if_bailout) {
CSA_ASSERT(this, TaggedIsNotSmi(function));
CSA_ASSERT(this, IsJSFunction(function));
CSA_ASSERT(this, IsClearWord32(LoadMapBitField(LoadMap(function)),
1 << Map::kHasNonInstancePrototype));
Node* proto_or_map =
LoadObjectField(function, JSFunction::kPrototypeOrInitialMapOffset);
GotoIf(IsTheHole(proto_or_map), if_bailout);
VARIABLE(var_result, MachineRepresentation::kTagged, proto_or_map);
Label done(this, &var_result);
GotoIfNot(IsMap(proto_or_map), &done);
var_result.Bind(LoadMapPrototype(proto_or_map));
Goto(&done);
BIND(&done);
return var_result.value();
}
Node* CodeStubAssembler::StoreHeapNumberValue(Node* object, Node* value) {
return StoreObjectFieldNoWriteBarrier(object, HeapNumber::kValueOffset, value,
MachineRepresentation::kFloat64);
......@@ -3159,12 +3180,28 @@ Node* CodeStubAssembler::IsMap(Node* map) {
return HasInstanceType(map, MAP_TYPE);
}
Node* CodeStubAssembler::IsJSValue(Node* map) {
return HasInstanceType(map, JS_VALUE_TYPE);
Node* CodeStubAssembler::IsJSValueInstanceType(Node* instance_type) {
return Word32Equal(instance_type, Int32Constant(JS_VALUE_TYPE));
}
Node* CodeStubAssembler::IsJSValue(Node* object) {
return IsJSValueMap(LoadMap(object));
}
Node* CodeStubAssembler::IsJSValueMap(Node* map) {
return IsJSValueInstanceType(LoadMapInstanceType(map));
}
Node* CodeStubAssembler::IsJSArrayInstanceType(Node* instance_type) {
return Word32Equal(instance_type, Int32Constant(JS_ARRAY_TYPE));
}
Node* CodeStubAssembler::IsJSArray(Node* object) {
return HasInstanceType(object, JS_ARRAY_TYPE);
return IsJSArrayMap(LoadMap(object));
}
Node* CodeStubAssembler::IsJSArrayMap(Node* map) {
return IsJSArrayInstanceType(LoadMapInstanceType(map));
}
Node* CodeStubAssembler::IsWeakCell(Node* object) {
......@@ -3238,8 +3275,16 @@ Node* CodeStubAssembler::IsUnseededNumberDictionary(Node* object) {
LoadRoot(Heap::kUnseededNumberDictionaryMapRootIndex));
}
Node* CodeStubAssembler::IsJSFunctionInstanceType(Node* instance_type) {
return Word32Equal(instance_type, Int32Constant(JS_FUNCTION_TYPE));
}
Node* CodeStubAssembler::IsJSFunction(Node* object) {
return HasInstanceType(object, JS_FUNCTION_TYPE);
return IsJSFunctionMap(LoadMap(object));
}
Node* CodeStubAssembler::IsJSFunctionMap(Node* map) {
return IsJSFunctionInstanceType(LoadMapInstanceType(map));
}
Node* CodeStubAssembler::IsJSTypedArray(Node* object) {
......@@ -5374,16 +5419,56 @@ Node* CodeStubAssembler::CallGetterIfAccessor(Node* value, Node* details,
// AccessorInfo case.
BIND(&if_accessor_info);
{
// TODO(ishell): Consider doing this for the Function.prototype and the
// String.length accessor infos as well.
Node* accessor_info = value;
CSA_ASSERT(this, IsAccessorInfo(value));
CSA_ASSERT(this, TaggedIsNotSmi(receiver));
GotoIfNot(IsJSArray(receiver), if_bailout);
// The only AccessorInfo on JSArray is the "length" property.
CSA_ASSERT(this, IsLengthString(
LoadObjectField(value, AccessorInfo::kNameOffset)));
var_value.Bind(LoadJSArrayLength(receiver));
Goto(&done);
Label if_array(this), if_function(this), if_value(this);
// Dispatch based on {receiver} instance type.
Node* receiver_map = LoadMap(receiver);
Node* receiver_instance_type = LoadMapInstanceType(receiver_map);
GotoIf(IsJSArrayInstanceType(receiver_instance_type), &if_array);
GotoIf(IsJSFunctionInstanceType(receiver_instance_type), &if_function);
Branch(IsJSValueInstanceType(receiver_instance_type), &if_value,
if_bailout);
// JSArray AccessorInfo case.
BIND(&if_array);
{
// The only AccessorInfo on JSArray is the "length" property.
CSA_ASSERT(this, IsLengthString(LoadObjectField(
accessor_info, AccessorInfo::kNameOffset)));
var_value.Bind(LoadJSArrayLength(receiver));
Goto(&done);
}
// JSFunction AccessorInfo case.
BIND(&if_function);
{
// We only deal with the "prototype" accessor on JSFunction here.
GotoIfNot(IsPrototypeString(
LoadObjectField(accessor_info, AccessorInfo::kNameOffset)),
if_bailout);
GotoIf(IsSetWord32(LoadMapBitField(receiver_map),
1 << Map::kHasNonInstancePrototype),
if_bailout);
var_value.Bind(LoadJSFunctionPrototype(receiver, if_bailout));
Goto(&done);
}
// JSValue AccessorInfo case.
BIND(&if_value);
{
// We only deal with the "length" accessor on JSValue string wrappers.
GotoIfNot(IsLengthString(
LoadObjectField(accessor_info, AccessorInfo::kNameOffset)),
if_bailout);
Node* receiver_value = LoadJSValueValue(receiver);
GotoIfNot(TaggedIsNotSmi(receiver_value), if_bailout);
GotoIfNot(IsString(receiver_value), if_bailout);
var_value.Bind(LoadStringLength(receiver_value));
Goto(&done);
}
}
BIND(&done);
......
......@@ -29,6 +29,7 @@ enum class PrimitiveType { kBoolean, kNumber, kString, kSymbol };
V(CodeMap, CodeMap) \
V(empty_string, EmptyString) \
V(length_string, LengthString) \
V(prototype_string, PrototypeString) \
V(EmptyFixedArray, EmptyFixedArray) \
V(FalseValue, False) \
V(FixedArrayMap, FixedArrayMap) \
......@@ -466,6 +467,9 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
Node* LoadJSArrayElementsMap(ElementsKind kind, Node* native_context);
// Load the "prototype" property of a JSFunction.
Node* LoadJSFunctionPrototype(Node* function, Label* if_bailout);
// Store the floating point value of a HeapNumber.
Node* StoreHeapNumberValue(Node* object, Node* value);
// Store a field to an object on the heap.
......@@ -751,8 +755,12 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
Node* IsName(Node* object);
Node* IsSymbol(Node* object);
Node* IsPrivateSymbol(Node* object);
Node* IsJSValueInstanceType(Node* instance_type);
Node* IsJSValue(Node* object);
Node* IsJSValueMap(Node* map);
Node* IsJSArrayInstanceType(Node* instance_type);
Node* IsJSArray(Node* object);
Node* IsJSArrayMap(Node* object);
Node* IsNativeContext(Node* object);
Node* IsWeakCell(Node* object);
Node* IsFixedDoubleArray(Node* object);
......@@ -760,7 +768,9 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
Node* IsDictionary(Node* object);
Node* IsUnseededNumberDictionary(Node* object);
Node* IsConstructorMap(Node* map);
Node* IsJSFunctionInstanceType(Node* instance_type);
Node* IsJSFunction(Node* object);
Node* IsJSFunctionMap(Node* object);
Node* IsJSTypedArray(Node* object);
Node* IsJSArrayBuffer(Node* object);
Node* IsFixedTypedArray(Node* object);
......
......@@ -1877,34 +1877,6 @@ void AccessorAssembler::LoadIC_Uninitialized(const LoadICParameters* p) {
LoadRoot(Heap::kpremonomorphic_symbolRootIndex),
SKIP_WRITE_BARRIER, 0, SMI_PARAMETERS);
Label not_function_prototype(this);
GotoIf(Word32NotEqual(instance_type, Int32Constant(JS_FUNCTION_TYPE)),
&not_function_prototype);
GotoIfNot(WordEqual(p->name, LoadRoot(Heap::kprototype_stringRootIndex)),
&not_function_prototype);
Node* bit_field = LoadMapBitField(receiver_map);
GotoIf(IsSetWord32(bit_field, 1 << Map::kHasNonInstancePrototype),
&not_function_prototype);
// Function.prototype load.
{
// TODO(jkummerow): Unify with LoadIC_FunctionPrototype builtin
// (when we have a shared CSA base class for all builtins).
Node* proto_or_map =
LoadObjectField(receiver, JSFunction::kPrototypeOrInitialMapOffset);
GotoIf(IsTheHole(proto_or_map), &miss);
VARIABLE(var_result, MachineRepresentation::kTagged, proto_or_map);
Label done(this, &var_result);
GotoIfNot(IsMap(proto_or_map), &done);
var_result.Bind(LoadMapPrototype(proto_or_map));
Goto(&done);
BIND(&done);
Return(var_result.value());
}
BIND(&not_function_prototype);
GenericPropertyLoad(receiver, receiver_map, instance_type, p->name, p, &miss,
kDontUseStubCache);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment