Commit 148e5e86 authored by Dan Elphick's avatar Dan Elphick Committed by Commit Bot

[cleanup] Move KeyedSloppyArguments funcs out of CSA

Moves all of the KeyedSloppyArguments functions out of CodeStubAssembler
and into builtins-handler-gen.cc which is the only place they're used.

Bug: v8:9810
Change-Id: Ie52bdf24b7890943b89007f566dd18fe644a5996
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1895558Reviewed-by: 's avatarJakob Gruber <jgruber@chromium.org>
Commit-Queue: Dan Elphick <delphick@chromium.org>
Cr-Commit-Position: refs/heads/master@{#64723}
parent fea98b6f
......@@ -40,8 +40,152 @@ class HandlerBuiltinsAssembler : public CodeStubAssembler {
void Generate_ElementsTransitionAndStore(KeyedAccessStoreMode store_mode);
void Generate_StoreFastElementIC(KeyedAccessStoreMode store_mode);
enum class ArgumentsAccessMode { kLoad, kStore, kHas };
// Emits keyed sloppy arguments has. Returns whether the key is in the
// arguments.
Node* HasKeyedSloppyArguments(Node* receiver, Node* key, Label* bailout) {
return EmitKeyedSloppyArguments(receiver, key, nullptr, bailout,
ArgumentsAccessMode::kHas);
}
// Emits keyed sloppy arguments load. Returns either the loaded value.
Node* LoadKeyedSloppyArguments(Node* receiver, Node* key, Label* bailout) {
return EmitKeyedSloppyArguments(receiver, key, nullptr, bailout,
ArgumentsAccessMode::kLoad);
}
// Emits keyed sloppy arguments store.
void StoreKeyedSloppyArguments(Node* receiver, Node* key, Node* value,
Label* bailout) {
DCHECK_NOT_NULL(value);
EmitKeyedSloppyArguments(receiver, key, value, bailout,
ArgumentsAccessMode::kStore);
}
private:
// Emits keyed sloppy arguments load if the |value| is nullptr or store
// otherwise. Returns either the loaded value or |value|.
Node* EmitKeyedSloppyArguments(Node* receiver, Node* key, Node* value,
Label* bailout,
ArgumentsAccessMode access_mode);
};
compiler::Node* HandlerBuiltinsAssembler::EmitKeyedSloppyArguments(
Node* receiver, Node* key, Node* value, Label* bailout,
ArgumentsAccessMode access_mode) {
// Mapped arguments are actual arguments. Unmapped arguments are values added
// to the arguments object after it was created for the call. Mapped arguments
// are stored in the context at indexes given by elements[key + 2]. Unmapped
// arguments are stored as regular indexed properties in the arguments array,
// held at elements[1]. See NewSloppyArguments() in runtime.cc for a detailed
// look at argument object construction.
//
// The sloppy arguments elements array has a special format:
//
// 0: context
// 1: unmapped arguments array
// 2: mapped_index0,
// 3: mapped_index1,
// ...
//
// length is 2 + min(number_of_actual_arguments, number_of_formal_arguments).
// If key + 2 >= elements.length then attempt to look in the unmapped
// arguments array (given by elements[1]) and return the value at key, missing
// to the runtime if the unmapped arguments array is not a fixed array or if
// key >= unmapped_arguments_array.length.
//
// Otherwise, t = elements[key + 2]. If t is the hole, then look up the value
// in the unmapped arguments array, as described above. Otherwise, t is a Smi
// index into the context array given at elements[0]. Return the value at
// context[t].
GotoIfNot(TaggedIsSmi(key), bailout);
key = SmiUntag(key);
GotoIf(IntPtrLessThan(key, IntPtrConstant(0)), bailout);
TNode<FixedArray> elements = CAST(LoadElements(receiver));
TNode<IntPtrT> elements_length = LoadAndUntagFixedArrayBaseLength(elements);
VARIABLE(var_result, MachineRepresentation::kTagged);
if (access_mode == ArgumentsAccessMode::kStore) {
var_result.Bind(value);
} else {
DCHECK(access_mode == ArgumentsAccessMode::kLoad ||
access_mode == ArgumentsAccessMode::kHas);
}
Label if_mapped(this), if_unmapped(this), end(this, &var_result);
TNode<IntPtrT> intptr_two = IntPtrConstant(2);
TNode<IntPtrT> adjusted_length = IntPtrSub(elements_length, intptr_two);
GotoIf(UintPtrGreaterThanOrEqual(key, adjusted_length), &if_unmapped);
TNode<Object> mapped_index =
LoadFixedArrayElement(elements, IntPtrAdd(key, intptr_two));
Branch(TaggedEqual(mapped_index, TheHoleConstant()), &if_unmapped,
&if_mapped);
BIND(&if_mapped);
{
TNode<IntPtrT> mapped_index_intptr = SmiUntag(CAST(mapped_index));
TNode<Context> the_context = CAST(LoadFixedArrayElement(elements, 0));
if (access_mode == ArgumentsAccessMode::kLoad) {
TNode<Object> result =
LoadContextElement(the_context, mapped_index_intptr);
CSA_ASSERT(this, TaggedNotEqual(result, TheHoleConstant()));
var_result.Bind(result);
} else if (access_mode == ArgumentsAccessMode::kHas) {
CSA_ASSERT(this, Word32BinaryNot(IsTheHole(LoadContextElement(
the_context, mapped_index_intptr))));
var_result.Bind(TrueConstant());
} else {
StoreContextElement(the_context, mapped_index_intptr, value);
}
Goto(&end);
}
BIND(&if_unmapped);
{
TNode<HeapObject> backing_store_ho =
CAST(LoadFixedArrayElement(elements, 1));
GotoIf(TaggedNotEqual(LoadMap(backing_store_ho), FixedArrayMapConstant()),
bailout);
TNode<FixedArray> backing_store = CAST(backing_store_ho);
TNode<IntPtrT> backing_store_length =
LoadAndUntagFixedArrayBaseLength(backing_store);
if (access_mode == ArgumentsAccessMode::kHas) {
Label out_of_bounds(this);
GotoIf(UintPtrGreaterThanOrEqual(key, backing_store_length),
&out_of_bounds);
TNode<Object> result = LoadFixedArrayElement(backing_store, key);
var_result.Bind(
SelectBooleanConstant(TaggedNotEqual(result, TheHoleConstant())));
Goto(&end);
BIND(&out_of_bounds);
var_result.Bind(FalseConstant());
Goto(&end);
} else {
GotoIf(UintPtrGreaterThanOrEqual(key, backing_store_length), bailout);
// The key falls into unmapped range.
if (access_mode == ArgumentsAccessMode::kLoad) {
TNode<Object> result = LoadFixedArrayElement(backing_store, key);
GotoIf(TaggedEqual(result, TheHoleConstant()), bailout);
var_result.Bind(result);
} else {
StoreFixedArrayElement(backing_store, key, value);
}
Goto(&end);
}
}
BIND(&end);
return var_result.value();
}
TF_BUILTIN(LoadIC_StringLength, CodeStubAssembler) {
Node* string = Parameter(Descriptor::kReceiver);
Return(LoadStringLengthAsSmi(string));
......@@ -416,7 +560,7 @@ TF_BUILTIN(StoreGlobalIC_Slow, CodeStubAssembler) {
receiver, name);
}
TF_BUILTIN(KeyedLoadIC_SloppyArguments, CodeStubAssembler) {
TF_BUILTIN(KeyedLoadIC_SloppyArguments, HandlerBuiltinsAssembler) {
Node* receiver = Parameter(Descriptor::kReceiver);
Node* key = Parameter(Descriptor::kName);
Node* slot = Parameter(Descriptor::kSlot);
......@@ -491,7 +635,7 @@ TF_BUILTIN(LoadIndexedInterceptorIC, CodeStubAssembler) {
vector);
}
TF_BUILTIN(KeyedHasIC_SloppyArguments, CodeStubAssembler) {
TF_BUILTIN(KeyedHasIC_SloppyArguments, HandlerBuiltinsAssembler) {
Node* receiver = Parameter(Descriptor::kReceiver);
Node* key = Parameter(Descriptor::kName);
Node* slot = Parameter(Descriptor::kSlot);
......
......@@ -9839,120 +9839,6 @@ TNode<IntPtrT> CodeStubAssembler::TryToIntptr(
return var_intptr_key.value();
}
Node* CodeStubAssembler::EmitKeyedSloppyArguments(
Node* receiver, Node* key, Node* value, Label* bailout,
ArgumentsAccessMode access_mode) {
// Mapped arguments are actual arguments. Unmapped arguments are values added
// to the arguments object after it was created for the call. Mapped arguments
// are stored in the context at indexes given by elements[key + 2]. Unmapped
// arguments are stored as regular indexed properties in the arguments array,
// held at elements[1]. See NewSloppyArguments() in runtime.cc for a detailed
// look at argument object construction.
//
// The sloppy arguments elements array has a special format:
//
// 0: context
// 1: unmapped arguments array
// 2: mapped_index0,
// 3: mapped_index1,
// ...
//
// length is 2 + min(number_of_actual_arguments, number_of_formal_arguments).
// If key + 2 >= elements.length then attempt to look in the unmapped
// arguments array (given by elements[1]) and return the value at key, missing
// to the runtime if the unmapped arguments array is not a fixed array or if
// key >= unmapped_arguments_array.length.
//
// Otherwise, t = elements[key + 2]. If t is the hole, then look up the value
// in the unmapped arguments array, as described above. Otherwise, t is a Smi
// index into the context array given at elements[0]. Return the value at
// context[t].
GotoIfNot(TaggedIsSmi(key), bailout);
key = SmiUntag(key);
GotoIf(IntPtrLessThan(key, IntPtrConstant(0)), bailout);
TNode<FixedArray> elements = CAST(LoadElements(receiver));
TNode<IntPtrT> elements_length = LoadAndUntagFixedArrayBaseLength(elements);
VARIABLE(var_result, MachineRepresentation::kTagged);
if (access_mode == ArgumentsAccessMode::kStore) {
var_result.Bind(value);
} else {
DCHECK(access_mode == ArgumentsAccessMode::kLoad ||
access_mode == ArgumentsAccessMode::kHas);
}
Label if_mapped(this), if_unmapped(this), end(this, &var_result);
TNode<IntPtrT> intptr_two = IntPtrConstant(2);
TNode<IntPtrT> adjusted_length = IntPtrSub(elements_length, intptr_two);
GotoIf(UintPtrGreaterThanOrEqual(key, adjusted_length), &if_unmapped);
TNode<Object> mapped_index =
LoadFixedArrayElement(elements, IntPtrAdd(key, intptr_two));
Branch(TaggedEqual(mapped_index, TheHoleConstant()), &if_unmapped,
&if_mapped);
BIND(&if_mapped);
{
TNode<IntPtrT> mapped_index_intptr = SmiUntag(CAST(mapped_index));
TNode<Context> the_context = CAST(LoadFixedArrayElement(elements, 0));
if (access_mode == ArgumentsAccessMode::kLoad) {
TNode<Object> result =
LoadContextElement(the_context, mapped_index_intptr);
CSA_ASSERT(this, TaggedNotEqual(result, TheHoleConstant()));
var_result.Bind(result);
} else if (access_mode == ArgumentsAccessMode::kHas) {
CSA_ASSERT(this, Word32BinaryNot(IsTheHole(LoadContextElement(
the_context, mapped_index_intptr))));
var_result.Bind(TrueConstant());
} else {
StoreContextElement(the_context, mapped_index_intptr, value);
}
Goto(&end);
}
BIND(&if_unmapped);
{
TNode<HeapObject> backing_store_ho =
CAST(LoadFixedArrayElement(elements, 1));
GotoIf(TaggedNotEqual(LoadMap(backing_store_ho), FixedArrayMapConstant()),
bailout);
TNode<FixedArray> backing_store = CAST(backing_store_ho);
TNode<IntPtrT> backing_store_length =
LoadAndUntagFixedArrayBaseLength(backing_store);
if (access_mode == ArgumentsAccessMode::kHas) {
Label out_of_bounds(this);
GotoIf(UintPtrGreaterThanOrEqual(key, backing_store_length),
&out_of_bounds);
TNode<Object> result = LoadFixedArrayElement(backing_store, key);
var_result.Bind(
SelectBooleanConstant(TaggedNotEqual(result, TheHoleConstant())));
Goto(&end);
BIND(&out_of_bounds);
var_result.Bind(FalseConstant());
Goto(&end);
} else {
GotoIf(UintPtrGreaterThanOrEqual(key, backing_store_length), bailout);
// The key falls into unmapped range.
if (access_mode == ArgumentsAccessMode::kLoad) {
TNode<Object> result = LoadFixedArrayElement(backing_store, key);
GotoIf(TaggedEqual(result, TheHoleConstant()), bailout);
var_result.Bind(result);
} else {
StoreFixedArrayElement(backing_store, key, value);
}
Goto(&end);
}
}
BIND(&end);
return var_result.value();
}
TNode<Context> CodeStubAssembler::LoadScriptContext(
TNode<Context> context, TNode<IntPtrT> context_index) {
TNode<NativeContext> native_context = LoadNativeContext(context);
......
......@@ -3206,28 +3206,6 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
TNode<Map> LoadReceiverMap(SloppyTNode<Object> receiver);
enum class ArgumentsAccessMode { kLoad, kStore, kHas };
// Emits keyed sloppy arguments has. Returns whether the key is in the
// arguments.
Node* HasKeyedSloppyArguments(Node* receiver, Node* key, Label* bailout) {
return EmitKeyedSloppyArguments(receiver, key, nullptr, bailout,
ArgumentsAccessMode::kHas);
}
// Emits keyed sloppy arguments load. Returns either the loaded value.
Node* LoadKeyedSloppyArguments(Node* receiver, Node* key, Label* bailout) {
return EmitKeyedSloppyArguments(receiver, key, nullptr, bailout,
ArgumentsAccessMode::kLoad);
}
// Emits keyed sloppy arguments store.
void StoreKeyedSloppyArguments(Node* receiver, Node* key, Node* value,
Label* bailout) {
DCHECK_NOT_NULL(value);
EmitKeyedSloppyArguments(receiver, key, value, bailout,
ArgumentsAccessMode::kStore);
}
// Loads script context from the script context table.
TNode<Context> LoadScriptContext(TNode<Context> context,
TNode<IntPtrT> context_index);
......@@ -3732,12 +3710,6 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
return Int32Constant(kSmiShiftSize + kSmiTagSize);
}
// Emits keyed sloppy arguments load if the |value| is nullptr or store
// otherwise. Returns either the loaded value or |value|.
Node* EmitKeyedSloppyArguments(Node* receiver, Node* key, Node* value,
Label* bailout,
ArgumentsAccessMode access_mode);
TNode<String> AllocateSlicedString(RootIndex map_root_index,
TNode<Uint32T> length,
TNode<String> parent, TNode<Smi> offset);
......
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