Chromium Code Reviews| 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) { |
|
mvstanton
2016/09/13 07:23:05
I recognize it's a "straight port" but it would be
Igor Sheludko
2016/09/13 07:43:24
Done.
|
| + // 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); |