| Index: src/code-stubs-hydrogen.cc
|
| diff --git a/src/code-stubs-hydrogen.cc b/src/code-stubs-hydrogen.cc
|
| index bdb3024f4b2c215795c3044b4183e850beb32cbb..b638c40673eb9a1449feb175f56717995c83a153 100644
|
| --- a/src/code-stubs-hydrogen.cc
|
| +++ b/src/code-stubs-hydrogen.cc
|
| @@ -62,8 +62,10 @@ class CodeStubGraphBuilderBase : public HGraphBuilder {
|
| protected:
|
| virtual void BuildCodeStub() = 0;
|
| HParameter* GetParameter(int parameter) { return parameters_[parameter]; }
|
| + CompilationInfo* info() { return &info_; }
|
| HydrogenCodeStub* stub() { return info_.code_stub(); }
|
| HContext* context() { return context_; }
|
| + Isolate* isolate() { return info_.isolate(); }
|
|
|
| private:
|
| SmartArrayPointer<HParameter*> parameters_;
|
| @@ -84,9 +86,6 @@ bool CodeStubGraphBuilderBase::BuildGraph() {
|
| graph()->entry_block()->Finish(jump);
|
| set_current_block(next_block);
|
|
|
| - context_ = new(zone()) HContext();
|
| - AddInstruction(context_);
|
| -
|
| int major_key = stub()->MajorKey();
|
| CodeStubInterfaceDescriptor* descriptor =
|
| info_.isolate()->code_stub_interface_descriptor(major_key);
|
| @@ -95,6 +94,11 @@ bool CodeStubGraphBuilderBase::BuildGraph() {
|
| }
|
| parameters_.Reset(new HParameter*[descriptor->register_param_count_]);
|
|
|
| + HConstant* undefined_constant = new(zone()) HConstant(
|
| + isolate()->factory()->undefined_value(), Representation::Tagged());
|
| + AddInstruction(undefined_constant);
|
| + graph()->set_undefined_constant(undefined_constant);
|
| +
|
| HGraph* graph = this->graph();
|
| Zone* zone = this->zone();
|
| for (int i = 0; i < descriptor->register_param_count_; ++i) {
|
| @@ -103,6 +107,10 @@ bool CodeStubGraphBuilderBase::BuildGraph() {
|
| graph->start_environment()->Push(param);
|
| parameters_[i] = param;
|
| }
|
| +
|
| + context_ = new(zone) HContext();
|
| + AddInstruction(context_);
|
| +
|
| AddSimulate(BailoutId::StubEntry());
|
|
|
| BuildCodeStub();
|
| @@ -144,4 +152,101 @@ Handle<Code> KeyedLoadFastElementStub::GenerateCode() {
|
| }
|
|
|
|
|
| +template <>
|
| +void CodeStubGraphBuilder<TransitionElementsKindStub>::BuildCodeStub() {
|
| + Zone* zone = this->zone();
|
| +
|
| + HValue* js_array = GetParameter(0);
|
| + HValue* map = GetParameter(1);
|
| +
|
| + info()->MarkAsSavesCallerDoubles();
|
| +
|
| + AddInstruction(new(zone) HTrapAllocationMemento(js_array));
|
| +
|
| + HInstruction* array_length =
|
| + AddInstruction(new(zone) HJSArrayLength(js_array,
|
| + js_array,
|
| + HType::Smi()));
|
| +
|
| + Heap* heap = isolate()->heap();
|
| + const int kMinFreeNewSpaceAfterGC =
|
| + ((heap->InitialSemiSpaceSize() - sizeof(FixedArrayBase)) / 2) /
|
| + kDoubleSize;
|
| +
|
| + HConstant* max_alloc_size =
|
| + new(zone) HConstant(kMinFreeNewSpaceAfterGC, Representation::Integer32());
|
| + AddInstruction(max_alloc_size);
|
| + AddInstruction(new(zone) HBoundsCheck(array_length, max_alloc_size));
|
| +
|
| + current_block()->UpdateEnvironment(new(zone) HEnvironment(zone));
|
| +
|
| + IfBuilder if_builder(this);
|
| +
|
| + if_builder.BeginTrue(array_length, graph()->GetConstant0(), Token::EQ);
|
| +
|
| + // Nothing to do, just change the map.
|
| +
|
| + if_builder.BeginFalse();
|
| +
|
| + HInstruction* elements =
|
| + AddInstruction(new(zone) HLoadElements(js_array, js_array));
|
| +
|
| + HInstruction* elements_length =
|
| + AddInstruction(new(zone) HFixedArrayBaseLength(elements));
|
| +
|
| + ElementsKind to_kind = casted_stub()->to_kind();
|
| + HValue* new_elements =
|
| + BuildAllocateElements(context(), to_kind, elements_length);
|
| +
|
| + // Fast elements kinds need to be initialized in case statements below cause a
|
| + // garbage collection.
|
| + Factory* factory = isolate()->factory();
|
| +
|
| + ASSERT(!IsFastSmiElementsKind(to_kind));
|
| + double nan_double = FixedDoubleArray::hole_nan_as_double();
|
| + HValue* hole = IsFastObjectElementsKind(to_kind)
|
| + ? AddInstruction(new(zone) HConstant(factory->the_hole_value(),
|
| + Representation::Tagged()))
|
| + : AddInstruction(new(zone) HConstant(nan_double,
|
| + Representation::Double()));
|
| +
|
| + LoopBuilder builder(this, context(), LoopBuilder::kPostIncrement);
|
| +
|
| + HValue* zero = graph()->GetConstant0();
|
| + HValue* start = IsFastElementsKind(to_kind) ? zero : array_length;
|
| + HValue* key = builder.BeginBody(start, elements_length, Token::LT);
|
| +
|
| + AddInstruction(new(zone) HStoreKeyed(new_elements, key, hole, to_kind));
|
| + AddSimulate(BailoutId::StubEntry(), REMOVABLE_SIMULATE);
|
| +
|
| + builder.EndBody();
|
| +
|
| + BuildCopyElements(context(), elements,
|
| + casted_stub()->from_kind(), new_elements,
|
| + to_kind, array_length);
|
| +
|
| + AddInstruction(new(zone) HStoreNamedField(js_array,
|
| + factory->elements_field_symbol(),
|
| + new_elements, true,
|
| + JSArray::kElementsOffset));
|
| + AddSimulate(BailoutId::StubEntry());
|
| +
|
| + if_builder.End();
|
| +
|
| + AddInstruction(new(zone) HStoreNamedField(js_array, factory->length_symbol(),
|
| + map, true, JSArray::kMapOffset));
|
| + AddSimulate(BailoutId::StubEntry());
|
| +
|
| + HReturn* ret = new(zone) HReturn(js_array, context());
|
| + current_block()->Finish(ret);
|
| +}
|
| +
|
| +
|
| +Handle<Code> TransitionElementsKindStub::GenerateCode() {
|
| + CodeStubGraphBuilder<TransitionElementsKindStub> builder(this);
|
| + LChunk* chunk = OptimizeGraph(builder.CreateGraph());
|
| + return chunk->Codegen(Code::COMPILED_STUB);
|
| +}
|
| +
|
| +
|
| } } // namespace v8::internal
|
|
|