diff options
Diffstat (limited to 'deps/v8/src/code-stubs-hydrogen.cc')
-rw-r--r-- | deps/v8/src/code-stubs-hydrogen.cc | 292 |
1 files changed, 226 insertions, 66 deletions
diff --git a/deps/v8/src/code-stubs-hydrogen.cc b/deps/v8/src/code-stubs-hydrogen.cc index 23d4269c84..dfa5ecd8cf 100644 --- a/deps/v8/src/code-stubs-hydrogen.cc +++ b/deps/v8/src/code-stubs-hydrogen.cc @@ -146,14 +146,10 @@ bool CodeStubGraphBuilderBase::BuildGraph() { int param_count = descriptor_->register_param_count_; HEnvironment* start_environment = graph()->start_environment(); HBasicBlock* next_block = CreateBasicBlock(start_environment); - current_block()->Goto(next_block); + Goto(next_block); next_block->SetJoinId(BailoutId::StubEntry()); set_current_block(next_block); - HConstant* undefined_constant = - Add<HConstant>(isolate()->factory()->undefined_value()); - graph()->set_undefined_constant(undefined_constant); - for (int i = 0; i < param_count; ++i) { HParameter* param = Add<HParameter>(i, HParameter::REGISTER_PARAMETER); @@ -162,7 +158,7 @@ bool CodeStubGraphBuilderBase::BuildGraph() { } HInstruction* stack_parameter_count; - if (descriptor_->stack_parameter_count_ != NULL) { + if (descriptor_->stack_parameter_count_.is_valid()) { ASSERT(descriptor_->environment_length() == (param_count + 1)); stack_parameter_count = New<HParameter>(param_count, HParameter::REGISTER_PARAMETER, @@ -178,8 +174,7 @@ bool CodeStubGraphBuilderBase::BuildGraph() { arguments_length_ = graph()->GetConstant0(); } - context_ = New<HContext>(); - AddInstruction(context_); + context_ = Add<HContext>(); start_environment->BindContext(context_); Add<HSimulate>(BailoutId::StubEntry()); @@ -207,8 +202,7 @@ bool CodeStubGraphBuilderBase::BuildGraph() { if (current_block() != NULL) { HReturn* hreturn_instruction = New<HReturn>(return_value, stack_pop_count); - current_block()->Finish(hreturn_instruction); - set_current_block(NULL); + FinishCurrentBlock(hreturn_instruction); } return true; } @@ -298,12 +292,21 @@ static Handle<Code> DoGenerateCode(Isolate* isolate, Stub* stub) { // the runtime that is significantly faster than using the standard // stub-failure deopt mechanism. if (stub->IsUninitialized() && descriptor->has_miss_handler()) { - ASSERT(descriptor->stack_parameter_count_ == NULL); + ASSERT(!descriptor->stack_parameter_count_.is_valid()); return stub->GenerateLightweightMissCode(isolate); } + ElapsedTimer timer; + if (FLAG_profile_hydrogen_code_stub_compilation) { + timer.Start(); + } CodeStubGraphBuilder<Stub> builder(isolate, stub); LChunk* chunk = OptimizeGraph(builder.CreateGraph()); - return chunk->Codegen(); + Handle<Code> code = chunk->Codegen(); + if (FLAG_profile_hydrogen_code_stub_compilation) { + double ms = timer.Elapsed().InMillisecondsF(); + PrintF("[Lazy compilation of %s took %0.3f ms]\n", *stub->GetName(), ms); + } + return code; } @@ -339,6 +342,19 @@ Handle<Code> ToNumberStub::GenerateCode(Isolate* isolate) { template <> +HValue* CodeStubGraphBuilder<NumberToStringStub>::BuildCodeStub() { + info()->MarkAsSavesCallerDoubles(); + HValue* number = GetParameter(NumberToStringStub::kNumber); + return BuildNumberToString(number, handle(Type::Number(), isolate())); +} + + +Handle<Code> NumberToStringStub::GenerateCode(Isolate* isolate) { + return DoGenerateCode(isolate, this); +} + + +template <> HValue* CodeStubGraphBuilder<FastCloneShallowArrayStub>::BuildCodeStub() { Factory* factory = isolate()->factory(); HValue* undefined = graph()->GetConstantUndefined(); @@ -355,42 +371,48 @@ HValue* CodeStubGraphBuilder<FastCloneShallowArrayStub>::BuildCodeStub() { undefined); checker.Then(); - HObjectAccess access = HObjectAccess::ForAllocationSiteTransitionInfo(); + HObjectAccess access = HObjectAccess::ForAllocationSiteOffset( + AllocationSite::kTransitionInfoOffset); HInstruction* boilerplate = Add<HLoadNamedField>(allocation_site, access); + HValue* push_value; if (mode == FastCloneShallowArrayStub::CLONE_ANY_ELEMENTS) { HValue* elements = AddLoadElements(boilerplate); IfBuilder if_fixed_cow(this); if_fixed_cow.If<HCompareMap>(elements, factory->fixed_cow_array_map()); if_fixed_cow.Then(); - environment()->Push(BuildCloneShallowArray(boilerplate, - allocation_site, - alloc_site_mode, - FAST_ELEMENTS, - 0/*copy-on-write*/)); + push_value = BuildCloneShallowArray(boilerplate, + allocation_site, + alloc_site_mode, + FAST_ELEMENTS, + 0/*copy-on-write*/); + environment()->Push(push_value); if_fixed_cow.Else(); IfBuilder if_fixed(this); if_fixed.If<HCompareMap>(elements, factory->fixed_array_map()); if_fixed.Then(); - environment()->Push(BuildCloneShallowArray(boilerplate, - allocation_site, - alloc_site_mode, - FAST_ELEMENTS, - length)); + push_value = BuildCloneShallowArray(boilerplate, + allocation_site, + alloc_site_mode, + FAST_ELEMENTS, + length); + environment()->Push(push_value); if_fixed.Else(); - environment()->Push(BuildCloneShallowArray(boilerplate, - allocation_site, - alloc_site_mode, - FAST_DOUBLE_ELEMENTS, - length)); + push_value = BuildCloneShallowArray(boilerplate, + allocation_site, + alloc_site_mode, + FAST_DOUBLE_ELEMENTS, + length); + environment()->Push(push_value); } else { ElementsKind elements_kind = casted_stub()->ComputeElementsKind(); - environment()->Push(BuildCloneShallowArray(boilerplate, - allocation_site, - alloc_site_mode, - elements_kind, - length)); + push_value = BuildCloneShallowArray(boilerplate, + allocation_site, + alloc_site_mode, + elements_kind, + length); + environment()->Push(push_value); } checker.ElseDeopt("Uninitialized boilerplate literals"); @@ -407,23 +429,33 @@ Handle<Code> FastCloneShallowArrayStub::GenerateCode(Isolate* isolate) { template <> HValue* CodeStubGraphBuilder<FastCloneShallowObjectStub>::BuildCodeStub() { - Zone* zone = this->zone(); HValue* undefined = graph()->GetConstantUndefined(); - HInstruction* boilerplate = Add<HLoadKeyed>(GetParameter(0), - GetParameter(1), - static_cast<HValue*>(NULL), - FAST_ELEMENTS); + HInstruction* allocation_site = Add<HLoadKeyed>(GetParameter(0), + GetParameter(1), + static_cast<HValue*>(NULL), + FAST_ELEMENTS); IfBuilder checker(this); - checker.IfNot<HCompareObjectEqAndBranch, HValue*>(boilerplate, + checker.IfNot<HCompareObjectEqAndBranch, HValue*>(allocation_site, undefined); checker.And(); + HObjectAccess access = HObjectAccess::ForAllocationSiteOffset( + AllocationSite::kTransitionInfoOffset); + HInstruction* boilerplate = Add<HLoadNamedField>(allocation_site, access); + int size = JSObject::kHeaderSize + casted_stub()->length() * kPointerSize; - HValue* boilerplate_size = - AddInstruction(new(zone) HInstanceSize(boilerplate)); - HValue* size_in_words = Add<HConstant>(size >> kPointerSizeLog2); + int object_size = size; + if (FLAG_allocation_site_pretenuring) { + size += AllocationMemento::kSize; + } + + HValue* boilerplate_map = Add<HLoadNamedField>( + boilerplate, HObjectAccess::ForMap()); + HValue* boilerplate_size = Add<HLoadNamedField>( + boilerplate_map, HObjectAccess::ForMapInstanceSize()); + HValue* size_in_words = Add<HConstant>(object_size >> kPointerSizeLog2); checker.If<HCompareNumericAndBranch>(boilerplate_size, size_in_words, Token::EQ); checker.Then(); @@ -433,12 +465,17 @@ HValue* CodeStubGraphBuilder<FastCloneShallowObjectStub>::BuildCodeStub() { HInstruction* object = Add<HAllocate>(size_in_bytes, HType::JSObject(), isolate()->heap()->GetPretenureMode(), JS_OBJECT_TYPE); - for (int i = 0; i < size; i += kPointerSize) { + for (int i = 0; i < object_size; i += kPointerSize) { HObjectAccess access = HObjectAccess::ForJSObjectOffset(i); Add<HStoreNamedField>(object, access, Add<HLoadNamedField>(boilerplate, access)); } + ASSERT(FLAG_allocation_site_pretenuring || (size == object_size)); + if (FLAG_allocation_site_pretenuring) { + BuildCreateAllocationMemento(object, object_size, allocation_site); + } + environment()->Push(object); checker.ElseDeopt("Uninitialized boilerplate in fast clone"); checker.End(); @@ -459,24 +496,39 @@ HValue* CodeStubGraphBuilder<CreateAllocationSiteStub>::BuildCodeStub() { JS_OBJECT_TYPE); // Store the map - Handle<Map> allocation_site_map(isolate()->heap()->allocation_site_map(), - isolate()); + Handle<Map> allocation_site_map = isolate()->factory()->allocation_site_map(); AddStoreMapConstant(object, allocation_site_map); // Store the payload (smi elements kind) HValue* initial_elements_kind = Add<HConstant>(GetInitialFastElementsKind()); Add<HStoreNamedField>(object, - HObjectAccess::ForAllocationSiteTransitionInfo(), + HObjectAccess::ForAllocationSiteOffset( + AllocationSite::kTransitionInfoOffset), initial_elements_kind); + // Unlike literals, constructed arrays don't have nested sites + Add<HStoreNamedField>(object, + HObjectAccess::ForAllocationSiteOffset( + AllocationSite::kNestedSiteOffset), + graph()->GetConstant0()); + + // Store an empty fixed array for the code dependency. + HConstant* empty_fixed_array = + Add<HConstant>(isolate()->factory()->empty_fixed_array()); + HStoreNamedField* store = Add<HStoreNamedField>( + object, + HObjectAccess::ForAllocationSiteOffset( + AllocationSite::kDependentCodeOffset), + empty_fixed_array); + // Link the object to the allocation site list HValue* site_list = Add<HConstant>( ExternalReference::allocation_sites_list_address(isolate())); HValue* site = Add<HLoadNamedField>(site_list, HObjectAccess::ForAllocationSiteList()); - HStoreNamedField* store = - Add<HStoreNamedField>(object, HObjectAccess::ForAllocationSiteWeakNext(), - site); + store = Add<HStoreNamedField>(object, + HObjectAccess::ForAllocationSiteOffset(AllocationSite::kWeakNextOffset), + site); store->SkipWriteBarrier(); Add<HStoreNamedField>(site_list, HObjectAccess::ForAllocationSiteList(), object); @@ -519,7 +571,7 @@ HValue* CodeStubGraphBuilder<LoadFieldStub>::BuildCodeStub() { HObjectAccess access = casted_stub()->is_inobject() ? HObjectAccess::ForJSObjectOffset(casted_stub()->offset(), rep) : HObjectAccess::ForBackingStoreOffset(casted_stub()->offset(), rep); - return AddInstruction(BuildLoadNamedField(GetParameter(0), access)); + return AddLoadNamedField(GetParameter(0), access); } @@ -534,7 +586,7 @@ HValue* CodeStubGraphBuilder<KeyedLoadFieldStub>::BuildCodeStub() { HObjectAccess access = casted_stub()->is_inobject() ? HObjectAccess::ForJSObjectOffset(casted_stub()->offset(), rep) : HObjectAccess::ForBackingStoreOffset(casted_stub()->offset(), rep); - return AddInstruction(BuildLoadNamedField(GetParameter(0), access)); + return AddLoadNamedField(GetParameter(0), access); } @@ -640,14 +692,13 @@ HValue* CodeStubGraphBuilderBase::BuildArraySingleArgumentConstructor( HValue* constant_zero = graph()->GetConstant0(); HInstruction* elements = Add<HArgumentsElements>(false); - HInstruction* argument = AddInstruction( - new(zone()) HAccessArgumentsAt(elements, constant_one, constant_zero)); + HInstruction* argument = Add<HAccessArgumentsAt>( + elements, constant_one, constant_zero); HConstant* max_alloc_length = Add<HConstant>(JSObject::kInitialMaxFastElementArray); const int initial_capacity = JSArray::kPreallocatedArrayElements; - HConstant* initial_capacity_node = New<HConstant>(initial_capacity); - AddInstruction(initial_capacity_node); + HConstant* initial_capacity_node = Add<HConstant>(initial_capacity); HInstruction* checked_arg = Add<HBoundsCheck>(argument, max_alloc_length); IfBuilder if_builder(this); @@ -690,8 +741,8 @@ HValue* CodeStubGraphBuilderBase::BuildArrayNArgumentsConstructor( HValue* start = graph()->GetConstant0(); HValue* key = builder.BeginBody(start, length, Token::LT); HInstruction* argument_elements = Add<HArgumentsElements>(false); - HInstruction* argument = AddInstruction(new(zone()) HAccessArgumentsAt( - argument_elements, length, key)); + HInstruction* argument = Add<HAccessArgumentsAt>( + argument_elements, length, key); Add<HStoreKeyed>(elements, key, argument, kind); builder.EndBody(); @@ -792,7 +843,7 @@ HValue* CodeStubGraphBuilder<CompareNilICStub>::BuildCodeInitializedStub() { HIfContinuation continuation; Handle<Map> sentinel_map(isolate->heap()->meta_map()); Handle<Type> type = stub->GetType(isolate, sentinel_map); - BuildCompareNil(GetParameter(0), type, RelocInfo::kNoPosition, &continuation); + BuildCompareNil(GetParameter(0), type, &continuation); IfBuilder if_nil(this, &continuation); if_nil.Then(); if (continuation.IsFalseReachable()) { @@ -812,6 +863,115 @@ Handle<Code> CompareNilICStub::GenerateCode(Isolate* isolate) { template <> +HValue* CodeStubGraphBuilder<BinaryOpStub>::BuildCodeInitializedStub() { + BinaryOpStub* stub = casted_stub(); + HValue* left = GetParameter(0); + HValue* right = GetParameter(1); + + Handle<Type> left_type = stub->GetLeftType(isolate()); + Handle<Type> right_type = stub->GetRightType(isolate()); + Handle<Type> result_type = stub->GetResultType(isolate()); + + ASSERT(!left_type->Is(Type::None()) && !right_type->Is(Type::None()) && + (stub->HasSideEffects(isolate()) || !result_type->Is(Type::None()))); + + HValue* result = NULL; + if (stub->operation() == Token::ADD && + (left_type->Maybe(Type::String()) || right_type->Maybe(Type::String())) && + !left_type->Is(Type::String()) && !right_type->Is(Type::String())) { + // For the generic add stub a fast case for string addition is performance + // critical. + if (left_type->Maybe(Type::String())) { + IfBuilder if_leftisstring(this); + if_leftisstring.If<HIsStringAndBranch>(left); + if_leftisstring.Then(); + { + Push(AddInstruction(BuildBinaryOperation( + stub->operation(), left, right, + handle(Type::String(), isolate()), right_type, + result_type, stub->fixed_right_arg(), true))); + } + if_leftisstring.Else(); + { + Push(AddInstruction(BuildBinaryOperation( + stub->operation(), left, right, + left_type, right_type, result_type, + stub->fixed_right_arg(), true))); + } + if_leftisstring.End(); + result = Pop(); + } else { + IfBuilder if_rightisstring(this); + if_rightisstring.If<HIsStringAndBranch>(right); + if_rightisstring.Then(); + { + Push(AddInstruction(BuildBinaryOperation( + stub->operation(), left, right, + left_type, handle(Type::String(), isolate()), + result_type, stub->fixed_right_arg(), true))); + } + if_rightisstring.Else(); + { + Push(AddInstruction(BuildBinaryOperation( + stub->operation(), left, right, + left_type, right_type, result_type, + stub->fixed_right_arg(), true))); + } + if_rightisstring.End(); + result = Pop(); + } + } else { + result = AddInstruction(BuildBinaryOperation( + stub->operation(), left, right, + left_type, right_type, result_type, + stub->fixed_right_arg(), true)); + } + + // If we encounter a generic argument, the number conversion is + // observable, thus we cannot afford to bail out after the fact. + if (!stub->HasSideEffects(isolate())) { + if (result_type->Is(Type::Smi())) { + if (stub->operation() == Token::SHR) { + // TODO(olivf) Replace this by a SmiTagU Instruction. + // 0x40000000: this number would convert to negative when interpreting + // the register as signed value; + IfBuilder if_of(this); + if_of.IfNot<HCompareNumericAndBranch>(result, + Add<HConstant>(static_cast<int>(SmiValuesAre32Bits() + ? 0x80000000 : 0x40000000)), Token::EQ_STRICT); + if_of.Then(); + if_of.ElseDeopt("UInt->Smi oveflow"); + if_of.End(); + } + } + result = EnforceNumberType(result, result_type); + } + + // Reuse the double box of one of the operands if we are allowed to (i.e. + // chained binops). + if (stub->CanReuseDoubleBox()) { + HValue* operand = (stub->mode() == OVERWRITE_LEFT) ? left : right; + IfBuilder if_heap_number(this); + if_heap_number.IfNot<HIsSmiAndBranch>(operand); + if_heap_number.Then(); + Add<HStoreNamedField>(operand, HObjectAccess::ForHeapNumberValue(), result); + Push(operand); + if_heap_number.Else(); + Push(result); + if_heap_number.End(); + result = Pop(); + } + + return result; +} + + +Handle<Code> BinaryOpStub::GenerateCode(Isolate* isolate) { + return DoGenerateCode(isolate, this); +} + + +template <> HValue* CodeStubGraphBuilder<ToBooleanStub>::BuildCodeInitializedStub() { ToBooleanStub* stub = casted_stub(); @@ -918,8 +1078,7 @@ void CodeStubGraphBuilderBase::BuildInstallOptimizedCode( HValue* native_context, HValue* code_object) { Counters* counters = isolate()->counters(); - AddIncrementCounter(counters->fast_new_closure_install_optimized(), - context()); + AddIncrementCounter(counters->fast_new_closure_install_optimized()); // TODO(fschneider): Idea: store proper code pointers in the optimized code // map and either unmangle them on marking or do nothing as the whole map is @@ -967,7 +1126,7 @@ void CodeStubGraphBuilderBase::BuildInstallFromOptimizedCodeMap( } is_optimized.Else(); { - AddIncrementCounter(counters->fast_new_closure_try_optimized(), context()); + AddIncrementCounter(counters->fast_new_closure_try_optimized()); // optimized_map points to fixed array of 3-element entries // (native context, optimized code, literals). // Map must never be empty, so check the first elements. @@ -1012,8 +1171,8 @@ void CodeStubGraphBuilderBase::BuildInstallFromOptimizedCodeMap( } restore_check.Else(); { - HValue* keyed_minus = AddInstruction(HSub::New(zone(), context(), key, - shared_function_entry_length)); + HValue* keyed_minus = AddUncasted<HSub>( + key, shared_function_entry_length); HInstruction* keyed_lookup = Add<HLoadKeyed>(optimized_map, keyed_minus, static_cast<HValue*>(NULL), FAST_ELEMENTS); IfBuilder done_check(this); @@ -1022,8 +1181,8 @@ void CodeStubGraphBuilderBase::BuildInstallFromOptimizedCodeMap( done_check.Then(); { // Hit: fetch the optimized code. - HValue* keyed_plus = AddInstruction(HAdd::New(zone(), context(), - keyed_minus, graph()->GetConstant1())); + HValue* keyed_plus = AddUncasted<HAdd>( + keyed_minus, graph()->GetConstant1()); HValue* code_object = Add<HLoadKeyed>(optimized_map, keyed_plus, static_cast<HValue*>(NULL), FAST_ELEMENTS); BuildInstallOptimizedCode(js_function, native_context, code_object); @@ -1052,11 +1211,12 @@ HValue* CodeStubGraphBuilder<FastNewClosureStub>::BuildCodeStub() { Add<HConstant>(factory->empty_fixed_array()); HValue* shared_info = GetParameter(0); + AddIncrementCounter(counters->fast_new_closure_total()); + // Create a new closure from the given function info in new space HValue* size = Add<HConstant>(JSFunction::kSize); HInstruction* js_function = Add<HAllocate>(size, HType::JSObject(), NOT_TENURED, JS_FUNCTION_TYPE); - AddIncrementCounter(counters->fast_new_closure_total(), context()); int map_index = Context::FunctionMapIndex(casted_stub()->language_mode(), casted_stub()->is_generator()); |