| Index: src/code-stub-assembler.cc
|
| diff --git a/src/code-stub-assembler.cc b/src/code-stub-assembler.cc
|
| index baf4c5e6b4a147441a210d64709076efd808859a..6c6920521de9efd45bb4f98d3cbace8222369748 100644
|
| --- a/src/code-stub-assembler.cc
|
| +++ b/src/code-stub-assembler.cc
|
| @@ -4339,6 +4339,105 @@ void CodeStubAssembler::StoreNamedField(Node* object, FieldIndex index,
|
| }
|
| }
|
|
|
| +Node* CodeStubAssembler::EmitKeyedSloppyArguments(Node* receiver, Node* key,
|
| + Node* value, Label* bailout) {
|
| + // 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].
|
| +
|
| + bool is_load = value == nullptr;
|
| +
|
| + GotoUnless(WordIsSmi(key), bailout);
|
| + key = SmiUntag(key);
|
| + GotoIf(IntPtrLessThan(key, IntPtrConstant(0)), bailout);
|
| +
|
| + Node* elements = LoadElements(receiver);
|
| + Node* elements_length = LoadAndUntagFixedArrayBaseLength(elements);
|
| +
|
| + Variable var_result(this, MachineRepresentation::kTagged);
|
| + if (!is_load) {
|
| + var_result.Bind(value);
|
| + }
|
| + Label if_mapped(this), if_unmapped(this), end(this, &var_result);
|
| + Node* intptr_two = IntPtrConstant(2);
|
| + Node* adjusted_length = IntPtrSub(elements_length, intptr_two);
|
| +
|
| + GotoIf(UintPtrGreaterThanOrEqual(key, adjusted_length), &if_unmapped);
|
| +
|
| + Node* mapped_index = LoadFixedArrayElement(
|
| + elements, IntPtrAdd(key, intptr_two), 0, INTPTR_PARAMETERS);
|
| + Branch(WordEqual(mapped_index, TheHoleConstant()), &if_unmapped, &if_mapped);
|
| +
|
| + Bind(&if_mapped);
|
| + {
|
| + Assert(WordIsSmi(mapped_index));
|
| + mapped_index = SmiUntag(mapped_index);
|
| + Node* the_context = LoadFixedArrayElement(elements, IntPtrConstant(0), 0,
|
| + INTPTR_PARAMETERS);
|
| + STATIC_ASSERT(Context::kHeaderSize == FixedArray::kHeaderSize);
|
| + if (is_load) {
|
| + Node* result = LoadFixedArrayElement(the_context, mapped_index, 0,
|
| + INTPTR_PARAMETERS);
|
| + Assert(WordNotEqual(result, TheHoleConstant()));
|
| + var_result.Bind(result);
|
| + } else {
|
| + StoreFixedArrayElement(the_context, mapped_index, value,
|
| + UPDATE_WRITE_BARRIER, INTPTR_PARAMETERS);
|
| + }
|
| + Goto(&end);
|
| + }
|
| +
|
| + Bind(&if_unmapped);
|
| + {
|
| + Node* backing_store = LoadFixedArrayElement(elements, IntPtrConstant(1), 0,
|
| + INTPTR_PARAMETERS);
|
| + GotoIf(WordNotEqual(LoadMap(backing_store),
|
| + LoadRoot(Heap::kFixedArrayMapRootIndex)),
|
| + bailout);
|
| +
|
| + Node* backing_store_length =
|
| + LoadAndUntagFixedArrayBaseLength(backing_store);
|
| + GotoIf(UintPtrGreaterThanOrEqual(key, backing_store_length), bailout);
|
| +
|
| + // The key falls into unmapped range.
|
| + if (is_load) {
|
| + Node* result =
|
| + LoadFixedArrayElement(backing_store, key, 0, INTPTR_PARAMETERS);
|
| + GotoIf(WordEqual(result, TheHoleConstant()), bailout);
|
| + var_result.Bind(result);
|
| + } else {
|
| + StoreFixedArrayElement(backing_store, key, value, UPDATE_WRITE_BARRIER,
|
| + INTPTR_PARAMETERS);
|
| + }
|
| + Goto(&end);
|
| + }
|
| +
|
| + Bind(&end);
|
| + return var_result.value();
|
| +}
|
| +
|
| Node* CodeStubAssembler::EnumLength(Node* map) {
|
| Node* bitfield_3 = LoadMapBitField3(map);
|
| Node* enum_length = BitFieldDecode<Map::EnumLengthBits>(bitfield_3);
|
|
|