diff options
Diffstat (limited to 'deps/v8/src/hydrogen.cc')
-rw-r--r-- | deps/v8/src/hydrogen.cc | 453 |
1 files changed, 318 insertions, 135 deletions
diff --git a/deps/v8/src/hydrogen.cc b/deps/v8/src/hydrogen.cc index 127d7a9aa1..e5270575e9 100644 --- a/deps/v8/src/hydrogen.cc +++ b/deps/v8/src/hydrogen.cc @@ -113,11 +113,10 @@ void HBasicBlock::AddInstruction(HInstruction* instr) { ASSERT(!IsStartBlock() || !IsFinished()); ASSERT(!instr->IsLinked()); ASSERT(!IsFinished()); - // Make sure that we never add instructions without knowing - // what the previous ast id is. - ASSERT(instr->IsSimulate() || instr->IsGoto() || - !last_environment()->previous_ast_id().IsNone()); + if (first_ == NULL) { + ASSERT(last_environment() != NULL); + ASSERT(!last_environment()->ast_id().IsNone()); HBlockEntry* entry = new(zone()) HBlockEntry(); entry->InitializeAsFirst(this); first_ = last_ = entry; @@ -184,7 +183,9 @@ void HBasicBlock::Finish(HControlInstruction* end) { } -void HBasicBlock::Goto(HBasicBlock* block, FunctionState* state) { +void HBasicBlock::Goto(HBasicBlock* block, + FunctionState* state, + bool add_simulate) { bool drop_extra = state != NULL && state->inlining_kind() == DROP_EXTRA_ON_RETURN; @@ -193,7 +194,7 @@ void HBasicBlock::Goto(HBasicBlock* block, FunctionState* state) { last_environment_ = last_environment()->DiscardInlined(drop_extra); } - AddSimulate(BailoutId::None()); + if (add_simulate) AddSimulate(BailoutId::None()); HGoto* instr = new(zone()) HGoto(block); Finish(instr); } @@ -215,12 +216,10 @@ void HBasicBlock::AddLeaveInlined(HValue* return_value, } -void HBasicBlock::SetInitialEnvironment(HEnvironment* env, - BailoutId previous_ast_id) { +void HBasicBlock::SetInitialEnvironment(HEnvironment* env) { ASSERT(!HasEnvironment()); ASSERT(first() == NULL); UpdateEnvironment(env); - env->set_previous_ast_id(previous_ast_id); } @@ -236,11 +235,7 @@ void HBasicBlock::SetJoinId(BailoutId ast_id) { predecessor->last_environment()->closure()->shared() ->VerifyBailoutId(ast_id))); simulate->set_ast_id(ast_id); - } - HEnvironment* last_environment = this->last_environment(); - ASSERT(last_environment || IsFinished()); - if (last_environment != NULL) { - last_environment->set_previous_ast_id(ast_id); + predecessor->last_environment()->set_ast_id(ast_id); } } @@ -301,9 +296,7 @@ void HBasicBlock::RegisterPredecessor(HBasicBlock* pred) { } } else if (!HasEnvironment() && !IsFinished()) { ASSERT(!IsLoopHeader()); - HEnvironment* new_env = pred->last_environment()->Copy(); - SetInitialEnvironment(new_env, - pred->last_environment()->previous_ast_id()); + SetInitialEnvironment(pred->last_environment()->Copy()); } predecessors_.Add(pred, zone()); @@ -553,6 +546,18 @@ void HGraph::Verify(bool do_full_verify) const { HPhi* phi = block->phis()->at(j); phi->Verify(); } + + // Check that all join blocks have predecessors that end with an + // unconditional goto and agree on their environment node id. + if (block->predecessors()->length() >= 2) { + BailoutId id = + block->predecessors()->first()->last_environment()->ast_id(); + for (int k = 0; k < block->predecessors()->length(); k++) { + HBasicBlock* predecessor = block->predecessors()->at(k); + ASSERT(predecessor->end()->IsGoto()); + ASSERT(predecessor->last_environment()->ast_id() == id); + } + } } // Check special property of first block to have no predecessors. @@ -639,25 +644,24 @@ DEFINE_GET_CONSTANT(Hole, the_hole, HType::Tagged(), false) HGraphBuilder::CheckBuilder::CheckBuilder(HGraphBuilder* builder) : builder_(builder), - finished_(false), - id_(builder->current_block()->last_environment()->previous_ast_id()) { + finished_(false) { HEnvironment* env = builder->environment(); - failure_block_ = builder->CreateBasicBlock(env->CopyWithoutHistory(), id_); - merge_block_ = builder->CreateBasicBlock(env->CopyWithoutHistory(), id_); + failure_block_ = builder->CreateBasicBlock(env->Copy()); + merge_block_ = builder->CreateBasicBlock(env->Copy()); } HValue* HGraphBuilder::CheckBuilder::CheckNotUndefined(HValue* value) { HEnvironment* env = builder_->environment(); - HIsNilAndBranch* compare = - new(zone()) HIsNilAndBranch(value, kStrictEquality, kUndefinedValue); - HBasicBlock* success_block = - builder_->CreateBasicBlock(env->CopyWithoutHistory(), id_); - HBasicBlock* failure_block = - builder_->CreateBasicBlock(env->CopyWithoutHistory(), id_); + HCompareObjectEqAndBranch* compare = + new(zone()) HCompareObjectEqAndBranch( + value, + builder_->graph()->GetConstantUndefined()); + HBasicBlock* success_block = builder_->CreateBasicBlock(env->Copy()); + HBasicBlock* failure_block = builder_->CreateBasicBlock(env->Copy()); compare->SetSuccessorAt(0, failure_block); compare->SetSuccessorAt(1, success_block); - failure_block->Goto(failure_block_); + failure_block->GotoNoSimulate(failure_block_); builder_->current_block()->Finish(compare); builder_->set_current_block(success_block); return compare; @@ -671,13 +675,11 @@ HValue* HGraphBuilder::CheckBuilder::CheckIntegerCompare(HValue* left, HCompareIDAndBranch* compare = new(zone()) HCompareIDAndBranch(left, right, op); compare->AssumeRepresentation(Representation::Integer32()); - HBasicBlock* success_block = - builder_->CreateBasicBlock(env->CopyWithoutHistory(), id_); - HBasicBlock* failure_block = - builder_->CreateBasicBlock(env->CopyWithoutHistory(), id_); + HBasicBlock* success_block = builder_->CreateBasicBlock(env->Copy()); + HBasicBlock* failure_block = builder_->CreateBasicBlock(env->Copy()); compare->SetSuccessorAt(0, success_block); compare->SetSuccessorAt(1, failure_block); - failure_block->Goto(failure_block_); + failure_block->GotoNoSimulate(failure_block_); builder_->current_block()->Finish(compare); builder_->set_current_block(success_block); return compare; @@ -692,11 +694,11 @@ HValue* HGraphBuilder::CheckBuilder::CheckIntegerEq(HValue* left, void HGraphBuilder::CheckBuilder::End() { ASSERT(!finished_); - builder_->current_block()->Goto(merge_block_); - failure_block_->SetJoinId(id_); - failure_block_->FinishExitWithDeoptimization(HDeoptimize::kUseAll); + builder_->current_block()->GotoNoSimulate(merge_block_); + if (failure_block_->HasPredecessor()) { + failure_block_->FinishExitWithDeoptimization(HDeoptimize::kUseAll); + } builder_->set_current_block(merge_block_); - merge_block_->SetJoinId(id_); finished_ = true; } @@ -706,19 +708,51 @@ HConstant* HGraph::GetInvalidContext() { } -HGraphBuilder::IfBuilder::IfBuilder(HGraphBuilder* builder) +HGraphBuilder::IfBuilder::IfBuilder(HGraphBuilder* builder, int position) : builder_(builder), + position_(position), finished_(false), + did_then_(false), did_else_(false), - id_(builder->current_block()->last_environment()->previous_ast_id()) { + deopt_then_(false), + deopt_else_(false), + did_and_(false), + did_or_(false), + captured_(false), + needs_compare_(true), + split_edge_merge_block_(NULL) { HEnvironment* env = builder->environment(); - first_true_block_ = builder->CreateBasicBlock(env->Copy(), id_); + first_true_block_ = builder->CreateBasicBlock(env->Copy()); last_true_block_ = NULL; - first_false_block_ = builder->CreateBasicBlock(env->Copy(), id_); + first_false_block_ = builder->CreateBasicBlock(env->Copy()); } -HInstruction* HGraphBuilder::IfBuilder::BeginIf( +HGraphBuilder::IfBuilder::IfBuilder( + HGraphBuilder* builder, + HIfContinuation* continuation) + : builder_(builder), + position_(RelocInfo::kNoPosition), + finished_(false), + did_then_(false), + did_else_(false), + deopt_then_(false), + deopt_else_(false), + did_and_(false), + did_or_(false), + captured_(false), + needs_compare_(false), + first_true_block_(NULL), + first_false_block_(NULL), + split_edge_merge_block_(NULL), + merge_block_(NULL) { + continuation->Continue(&first_true_block_, + &first_false_block_, + &position_); +} + + +HInstruction* HGraphBuilder::IfBuilder::IfCompare( HValue* left, HValue* right, Token::Value token, @@ -728,58 +762,148 @@ HInstruction* HGraphBuilder::IfBuilder::BeginIf( compare->set_observed_input_representation(input_representation, input_representation); compare->ChangeRepresentation(input_representation); - compare->SetSuccessorAt(0, first_true_block_); - compare->SetSuccessorAt(1, first_false_block_); - builder_->current_block()->Finish(compare); - builder_->set_current_block(first_true_block_); + AddCompare(compare); return compare; } -HInstruction* HGraphBuilder::IfBuilder::BeginIfObjectsEqual( - HValue* left, - HValue* right) { - HCompareObjectEqAndBranch* compare = - new(zone()) HCompareObjectEqAndBranch(left, right); - compare->SetSuccessorAt(0, first_true_block_); - compare->SetSuccessorAt(1, first_false_block_); - builder_->current_block()->Finish(compare); - builder_->set_current_block(first_true_block_); +HInstruction* HGraphBuilder::IfBuilder::IfCompareMap(HValue* left, + Handle<Map> map) { + HCompareMap* compare = + new(zone()) HCompareMap(left, map, + first_true_block_, first_false_block_); + AddCompare(compare); return compare; } -HInstruction* HGraphBuilder::IfBuilder::BeginIfMapEquals(HValue* value, - Handle<Map> map) { - HCompareMap* compare = new(zone()) - HCompareMap(value, map, first_true_block_, first_false_block_); +void HGraphBuilder::IfBuilder::AddCompare(HControlInstruction* compare) { + if (split_edge_merge_block_ != NULL) { + HEnvironment* env = first_false_block_->last_environment(); + HBasicBlock* split_edge = + builder_->CreateBasicBlock(env->Copy()); + if (did_or_) { + compare->SetSuccessorAt(0, split_edge); + compare->SetSuccessorAt(1, first_false_block_); + } else { + compare->SetSuccessorAt(0, first_true_block_); + compare->SetSuccessorAt(1, split_edge); + } + split_edge->GotoNoSimulate(split_edge_merge_block_); + } else { + compare->SetSuccessorAt(0, first_true_block_); + compare->SetSuccessorAt(1, first_false_block_); + } builder_->current_block()->Finish(compare); + needs_compare_ = false; +} + + +void HGraphBuilder::IfBuilder::Or() { + ASSERT(!did_and_); + did_or_ = true; + HEnvironment* env = first_false_block_->last_environment(); + if (split_edge_merge_block_ == NULL) { + split_edge_merge_block_ = + builder_->CreateBasicBlock(env->Copy()); + first_true_block_->GotoNoSimulate(split_edge_merge_block_); + first_true_block_ = split_edge_merge_block_; + } + builder_->set_current_block(first_false_block_); + first_false_block_ = builder_->CreateBasicBlock(env->Copy()); +} + + +void HGraphBuilder::IfBuilder::And() { + ASSERT(!did_or_); + did_and_ = true; + HEnvironment* env = first_false_block_->last_environment(); + if (split_edge_merge_block_ == NULL) { + split_edge_merge_block_ = builder_->CreateBasicBlock(env->Copy()); + first_false_block_->GotoNoSimulate(split_edge_merge_block_); + first_false_block_ = split_edge_merge_block_; + } + builder_->set_current_block(first_true_block_); + first_true_block_ = builder_->CreateBasicBlock(env->Copy()); +} + + +void HGraphBuilder::IfBuilder::CaptureContinuation( + HIfContinuation* continuation) { + ASSERT(!finished_); + ASSERT(!captured_); + HBasicBlock* true_block = last_true_block_ == NULL + ? first_true_block_ + : last_true_block_; + HBasicBlock* false_block = + did_else_ ? builder_->current_block() : first_false_block_; + continuation->Capture(true_block, false_block, position_); + captured_ = true; + End(); +} + + +void HGraphBuilder::IfBuilder::Then() { + ASSERT(!captured_); + ASSERT(!finished_); + did_then_ = true; + if (needs_compare_) { + // Handle if's without any expressions, they jump directly to the "else" + // branch. + builder_->current_block()->GotoNoSimulate(first_false_block_); + first_true_block_ = NULL; + } builder_->set_current_block(first_true_block_); - return compare; } -void HGraphBuilder::IfBuilder::BeginElse() { +void HGraphBuilder::IfBuilder::Else() { + ASSERT(did_then_); + ASSERT(!captured_); + ASSERT(!finished_); last_true_block_ = builder_->current_block(); - ASSERT(!last_true_block_->IsFinished()); + ASSERT(first_true_block_ == NULL || !last_true_block_->IsFinished()); builder_->set_current_block(first_false_block_); did_else_ = true; } +void HGraphBuilder::IfBuilder::Deopt() { + ASSERT(!(did_then_ ^ did_else_)); + HBasicBlock* block = builder_->current_block(); + block->FinishExitWithDeoptimization(HDeoptimize::kUseAll); + if (did_else_) { + first_false_block_ = NULL; + did_else_ = false; + } else { + first_true_block_ = NULL; + } +} + + void HGraphBuilder::IfBuilder::End() { - ASSERT(!finished_); - if (!did_else_) BeginElse(); - ASSERT(!last_true_block_->IsFinished()); - HBasicBlock* last_false_block = builder_->current_block(); - ASSERT(!last_false_block->IsFinished()); - HEnvironment* merge_env = - last_true_block_->last_environment()->CopyWithoutHistory(); - merge_block_ = builder_->CreateBasicBlock(merge_env, id_); - last_true_block_->Goto(merge_block_); - last_false_block->Goto(merge_block_); - merge_block_->SetJoinId(id_); - builder_->set_current_block(merge_block_); + if (!captured_) { + ASSERT(did_then_); + if (!did_else_) { + last_true_block_ = builder_->current_block(); + } + if (first_true_block_ == NULL) { + // Deopt on true. Nothing to do, just continue the else block. + } else if (first_false_block_ == NULL) { + builder_->set_current_block(last_true_block_); + } else { + HEnvironment* merge_env = last_true_block_->last_environment()->Copy(); + merge_block_ = builder_->CreateBasicBlock(merge_env); + ASSERT(!finished_); + if (!did_else_) Else(); + ASSERT(!last_true_block_->IsFinished()); + HBasicBlock* last_false_block = builder_->current_block(); + ASSERT(!last_false_block->IsFinished()); + last_true_block_->GotoNoSimulate(merge_block_); + last_false_block->GotoNoSimulate(merge_block_); + builder_->set_current_block(merge_block_); + } + } finished_ = true; } @@ -790,9 +914,8 @@ HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder, : builder_(builder), context_(context), direction_(direction), - id_(builder->current_block()->last_environment()->previous_ast_id()), finished_(false) { - header_block_ = builder->CreateLoopHeaderBlock(id_); + header_block_ = builder->CreateLoopHeaderBlock(); body_block_ = NULL; exit_block_ = NULL; } @@ -809,12 +932,12 @@ HValue* HGraphBuilder::LoopBuilder::BeginBody( phi_->AddInput(initial); phi_->ChangeRepresentation(Representation::Integer32()); env->Push(initial); - builder_->current_block()->Goto(header_block_); + builder_->current_block()->GotoNoSimulate(header_block_); HEnvironment* body_env = env->Copy(); HEnvironment* exit_env = env->Copy(); - body_block_ = builder_->CreateBasicBlock(body_env, id_); - exit_block_ = builder_->CreateBasicBlock(exit_env, id_); + body_block_ = builder_->CreateBasicBlock(body_env); + exit_block_ = builder_->CreateBasicBlock(exit_env); // Remove the phi from the expression stack body_env->Pop(); @@ -863,9 +986,8 @@ void HGraphBuilder::LoopBuilder::EndBody() { // Push the new increment value on the expression stack to merge into the phi. builder_->environment()->Push(increment_); - builder_->current_block()->Goto(header_block_); + builder_->current_block()->GotoNoSimulate(header_block_); header_block_->loop_information()->RegisterBackEdge(body_block_); - header_block_->SetJoinId(id_); builder_->set_current_block(exit_block_); // Pop the phi from the expression stack @@ -900,7 +1022,6 @@ void HGraphBuilder::AddSimulate(BailoutId id, ASSERT(current_block() != NULL); ASSERT(no_side_effects_scope_count_ == 0); current_block()->AddSimulate(id, removable); - environment()->set_previous_ast_id(id); } @@ -935,23 +1056,37 @@ HReturn* HGraphBuilder::AddReturn(HValue* value) { } -HBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env, - BailoutId previous_ast_id) { +HBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env) { HBasicBlock* b = graph()->CreateBasicBlock(); - b->SetInitialEnvironment(env, previous_ast_id); + b->SetInitialEnvironment(env); return b; } -HBasicBlock* HGraphBuilder::CreateLoopHeaderBlock(BailoutId previous_ast_id) { +HBasicBlock* HGraphBuilder::CreateLoopHeaderBlock() { HBasicBlock* header = graph()->CreateBasicBlock(); HEnvironment* entry_env = environment()->CopyAsLoopHeader(header); - header->SetInitialEnvironment(entry_env, previous_ast_id); + header->SetInitialEnvironment(entry_env); header->AttachLoopInformation(); return header; } +HValue* HGraphBuilder::BuildCheckNonSmi(HValue* obj) { + HCheckNonSmi* check = new(zone()) HCheckNonSmi(obj); + AddInstruction(check); + return check; +} + + +HValue* HGraphBuilder::BuildCheckMap(HValue* obj, + Handle<Map> map) { + HCheckMaps* check = new(zone()) HCheckMaps(obj, map, zone()); + AddInstruction(check); + return check; +} + + HInstruction* HGraphBuilder::BuildExternalArrayElementAccess( HValue* external_elements, HValue* checked_key, @@ -1049,14 +1184,16 @@ HValue* HGraphBuilder::BuildCheckForCapacityGrow(HValue* object, Zone* zone = this->zone(); IfBuilder length_checker(this); - length_checker.BeginIf(length, key, Token::EQ); + length_checker.IfCompare(length, key, Token::EQ); + length_checker.Then(); HValue* current_capacity = AddInstruction(new(zone) HFixedArrayBaseLength(elements)); IfBuilder capacity_checker(this); - capacity_checker.BeginIf(length, current_capacity, Token::EQ); + capacity_checker.IfCompare(length, current_capacity, Token::EQ); + capacity_checker.Then(); HValue* context = environment()->LookupContext(); @@ -1068,7 +1205,7 @@ HValue* HGraphBuilder::BuildCheckForCapacityGrow(HValue* object, new_capacity); environment()->Push(new_elements); - capacity_checker.BeginElse(); + capacity_checker.Else(); environment()->Push(elements); capacity_checker.End(); @@ -1088,7 +1225,7 @@ HValue* HGraphBuilder::BuildCheckForCapacityGrow(HValue* object, length_store->SetGVNFlag(kChangesArrayLengths); } - length_checker.BeginElse(); + length_checker.Else(); AddBoundsCheck(key, length, ALLOW_SMI_KEY); environment()->Push(elements); @@ -1108,19 +1245,19 @@ HValue* HGraphBuilder::BuildCopyElementsOnWrite(HValue* object, IfBuilder cow_checker(this); - cow_checker.BeginIfMapEquals(elements, - Handle<Map>(heap->fixed_cow_array_map())); + cow_checker.IfCompareMap(elements, + Handle<Map>(heap->fixed_cow_array_map())); + cow_checker.Then(); HValue* capacity = AddInstruction(new(zone) HFixedArrayBaseLength(elements)); HValue* new_elements = BuildGrowElementsCapacity(object, elements, - kind, length, - capacity); + kind, length, capacity); environment()->Push(new_elements); - cow_checker.BeginElse(); + cow_checker.Else(); environment()->Push(elements); @@ -1175,11 +1312,13 @@ HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess( HValue* checked_key = NULL; if (IsExternalArrayElementsKind(elements_kind)) { if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) { + NoObservableSideEffectsScope no_effects(this); HLoadExternalArrayPointer* external_elements = new(zone) HLoadExternalArrayPointer(elements); AddInstruction(external_elements); IfBuilder length_checker(this); - length_checker.BeginIf(key, length, Token::LT); + length_checker.IfCompare(key, length, Token::LT); + length_checker.Then(); CheckBuilder negative_checker(this); HValue* bounds_check = negative_checker.CheckIntegerCompare( key, graph()->GetConstant0(), Token::GTE); @@ -1216,7 +1355,11 @@ HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess( elements = BuildCheckForCapacityGrow(object, elements, elements_kind, length, key, is_js_array); - checked_key = key; + if (!key->type().IsSmi()) { + checked_key = AddInstruction(new(zone) HCheckSmiOrInt32(key)); + } else { + checked_key = key; + } } else { checked_key = AddBoundsCheck( key, length, ALLOW_SMI_KEY, checked_index_representation); @@ -1307,8 +1450,7 @@ void HGraphBuilder::BuildInitializeElements(HValue* elements, HValue* HGraphBuilder::BuildAllocateAndInitializeElements(HValue* context, ElementsKind kind, HValue* capacity) { - HValue* new_elements = - BuildAllocateElements(context, kind, capacity); + HValue* new_elements = BuildAllocateElements(context, kind, capacity); BuildInitializeElements(new_elements, kind, capacity); return new_elements; } @@ -1684,9 +1826,9 @@ HGraph::HGraph(CompilationInfo* info) start_environment_ = new(zone_) HEnvironment(NULL, info->scope(), info->closure(), zone_); } + start_environment_->set_ast_id(BailoutId::FunctionEntry()); entry_block_ = CreateBasicBlock(); - entry_block_->SetInitialEnvironment(start_environment_, - BailoutId::FunctionEntry()); + entry_block_->SetInitialEnvironment(start_environment_); } @@ -3839,8 +3981,8 @@ bool Uint32Analysis::CheckPhiOperands(HPhi* phi) { HValue* operand = phi->OperandAt(j); if (!operand->CheckFlag(HInstruction::kUint32)) { // Lazyly mark constants that fit into uint32 range with kUint32 flag. - if (operand->IsConstant() && - HConstant::cast(operand)->IsUint32()) { + if (operand->IsInteger32Constant() && + operand->GetInteger32Constant() >= 0) { operand->SetFlag(HInstruction::kUint32); continue; } @@ -4099,6 +4241,22 @@ void EffectContext::ReturnControl(HControlInstruction* instr, } +void EffectContext::ReturnContinuation(HIfContinuation* continuation, + BailoutId ast_id) { + HBasicBlock* true_branch = NULL; + HBasicBlock* false_branch = NULL; + continuation->Continue(&true_branch, &false_branch, NULL); + if (!continuation->IsTrueReachable()) { + owner()->set_current_block(false_branch); + } else if (!continuation->IsFalseReachable()) { + owner()->set_current_block(true_branch); + } else { + HBasicBlock* join = owner()->CreateJoin(true_branch, false_branch, ast_id); + owner()->set_current_block(join); + } +} + + void ValueContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) { ASSERT(!instr->IsControlInstruction()); if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) { @@ -4132,6 +4290,29 @@ void ValueContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) { } +void ValueContext::ReturnContinuation(HIfContinuation* continuation, + BailoutId ast_id) { + HBasicBlock* materialize_true = NULL; + HBasicBlock* materialize_false = NULL; + continuation->Continue(&materialize_true, &materialize_false, NULL); + if (continuation->IsTrueReachable()) { + owner()->set_current_block(materialize_true); + owner()->Push(owner()->graph()->GetConstantTrue()); + owner()->set_current_block(materialize_true); + } + if (continuation->IsFalseReachable()) { + owner()->set_current_block(materialize_false); + owner()->Push(owner()->graph()->GetConstantFalse()); + owner()->set_current_block(materialize_false); + } + if (continuation->TrueAndFalseReachable()) { + HBasicBlock* join = + owner()->CreateJoin(materialize_true, materialize_false, ast_id); + owner()->set_current_block(join); + } +} + + void TestContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) { ASSERT(!instr->IsControlInstruction()); HOptimizedGraphBuilder* builder = owner(); @@ -4160,6 +4341,21 @@ void TestContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) { } +void TestContext::ReturnContinuation(HIfContinuation* continuation, + BailoutId ast_id) { + HBasicBlock* true_branch = NULL; + HBasicBlock* false_branch = NULL; + continuation->Continue(&true_branch, &false_branch, NULL); + if (continuation->IsTrueReachable()) { + true_branch->Goto(if_true(), owner()->function_state()); + } + if (continuation->IsFalseReachable()) { + false_branch->Goto(if_false(), owner()->function_state()); + } + owner()->set_current_block(NULL); +} + + void TestContext::BuildBranch(HValue* value) { // We expect the graph to be in edge-split form: there is no edge that // connects a branch node to a join node. We conservatively ensure that @@ -4296,8 +4492,7 @@ bool HOptimizedGraphBuilder::BuildGraph() { // values (but not instructions), present in the initial environment and // not replayed by the Lithium translation. HEnvironment* initial_env = environment()->CopyWithoutHistory(); - HBasicBlock* body_entry = CreateBasicBlock(initial_env, - BailoutId::FunctionEntry()); + HBasicBlock* body_entry = CreateBasicBlock(initial_env); current_block()->Goto(body_entry); body_entry->SetJoinId(BailoutId::FunctionEntry()); set_current_block(body_entry); @@ -5541,7 +5736,7 @@ void HOptimizedGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { ASSERT(current_block()->HasPredecessor()); ASSERT(current_block() != NULL); bool osr_entry = PreProcessOsrEntry(stmt); - HBasicBlock* loop_entry = CreateLoopHeaderBlock(stmt->EntryId()); + HBasicBlock* loop_entry = CreateLoopHeaderBlock(); current_block()->Goto(loop_entry); set_current_block(loop_entry); if (osr_entry) graph()->set_osr_loop_entry(loop_entry); @@ -5584,7 +5779,7 @@ void HOptimizedGraphBuilder::VisitWhileStatement(WhileStatement* stmt) { ASSERT(current_block()->HasPredecessor()); ASSERT(current_block() != NULL); bool osr_entry = PreProcessOsrEntry(stmt); - HBasicBlock* loop_entry = CreateLoopHeaderBlock(stmt->EntryId()); + HBasicBlock* loop_entry = CreateLoopHeaderBlock(); current_block()->Goto(loop_entry); set_current_block(loop_entry); if (osr_entry) graph()->set_osr_loop_entry(loop_entry); @@ -5631,7 +5826,7 @@ void HOptimizedGraphBuilder::VisitForStatement(ForStatement* stmt) { } ASSERT(current_block() != NULL); bool osr_entry = PreProcessOsrEntry(stmt); - HBasicBlock* loop_entry = CreateLoopHeaderBlock(stmt->EntryId()); + HBasicBlock* loop_entry = CreateLoopHeaderBlock(); current_block()->Goto(loop_entry); set_current_block(loop_entry); if (osr_entry) graph()->set_osr_loop_entry(loop_entry); @@ -5726,7 +5921,7 @@ void HOptimizedGraphBuilder::VisitForInStatement(ForInStatement* stmt) { HForInCacheArray::cast(index_cache)); bool osr_entry = PreProcessOsrEntry(stmt); - HBasicBlock* loop_entry = CreateLoopHeaderBlock(stmt->EntryId()); + HBasicBlock* loop_entry = CreateLoopHeaderBlock(); current_block()->Goto(loop_entry); set_current_block(loop_entry); if (osr_entry) graph()->set_osr_loop_entry(loop_entry); @@ -6804,7 +6999,6 @@ void HOptimizedGraphBuilder::HandlePropertyAssignment(Assignment* expr) { true, // is_store &has_side_effects); Push(value); - ASSERT(has_side_effects); // Stores always have side effects. AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); return ast_context()->ReturnValue(Pop()); } @@ -8279,7 +8473,6 @@ bool HOptimizedGraphBuilder::TryInline(CallKind call_kind, AddSimulate(return_id); current_block()->UpdateEnvironment(inner_env); - inner_env->set_previous_ast_id(BailoutId::FunctionEntry()); ZoneList<HValue*>* arguments_values = NULL; // If the function uses arguments copy current arguments values @@ -8547,6 +8740,18 @@ bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall( return true; } break; + case kStringFromCharCode: + if (argument_count == 2 && check_type == RECEIVER_MAP_CHECK) { + AddCheckConstantFunction(expr->holder(), receiver, receiver_map); + HValue* argument = Pop(); + HValue* context = environment()->LookupContext(); + Drop(1); // Receiver. + HInstruction* result = + HStringCharFromCode::New(zone(), context, argument); + ast_context()->ReturnInstruction(result, expr->id()); + return true; + } + break; case kMathExp: if (!FLAG_fast_math) break; // Fall through if FLAG_fast_math. @@ -8600,9 +8805,7 @@ bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall( } else if (exponent == 2.0) { result = HMul::New(zone(), context, left, left); } - } else if (right->IsConstant() && - HConstant::cast(right)->HasInteger32Value() && - HConstant::cast(right)->Integer32Value() == 2) { + } else if (right->EqualsInteger32Constant(2)) { result = HMul::New(zone(), context, left, left); } @@ -9160,7 +9363,6 @@ void HOptimizedGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) { case Token::DELETE: return VisitDelete(expr); case Token::VOID: return VisitVoid(expr); case Token::TYPEOF: return VisitTypeof(expr); - case Token::ADD: return VisitAdd(expr); case Token::SUB: return VisitSub(expr); case Token::BIT_NOT: return VisitBitNot(expr); case Token::NOT: return VisitNot(expr); @@ -9218,21 +9420,6 @@ void HOptimizedGraphBuilder::VisitTypeof(UnaryOperation* expr) { } -void HOptimizedGraphBuilder::VisitAdd(UnaryOperation* expr) { - CHECK_ALIVE(VisitForValue(expr->expression())); - HValue* value = Pop(); - HValue* context = environment()->LookupContext(); - HInstruction* instr = - HMul::New(zone(), context, value, graph()->GetConstant1()); - if (instr->IsBinaryOperation()) { - // Since we don't have type feedback, we must be cautious/pessimistic. - HBinaryOperation::cast(instr)->set_observed_input_representation( - Representation::Tagged(), Representation::Tagged()); - } - return ast_context()->ReturnInstruction(instr, expr->id()); -} - - void HOptimizedGraphBuilder::VisitSub(UnaryOperation* expr) { CHECK_ALIVE(VisitForValue(expr->expression())); HValue* value = Pop(); @@ -11033,7 +11220,6 @@ HEnvironment::HEnvironment(HEnvironment* outer, pop_count_(0), push_count_(0), ast_id_(BailoutId::None()), - previous_ast_id_(BailoutId::None()), zone_(zone) { Initialize(scope->num_parameters() + 1, scope->num_stack_slots(), 0); } @@ -11050,7 +11236,6 @@ HEnvironment::HEnvironment(Zone* zone, int parameter_count) pop_count_(0), push_count_(0), ast_id_(BailoutId::None()), - previous_ast_id_(BailoutId::None()), zone_(zone) { Initialize(parameter_count, 0, 0); } @@ -11067,7 +11252,6 @@ HEnvironment::HEnvironment(const HEnvironment* other, Zone* zone) pop_count_(0), push_count_(0), ast_id_(other->ast_id()), - previous_ast_id_(BailoutId::None()), zone_(zone) { Initialize(other); } @@ -11088,7 +11272,6 @@ HEnvironment::HEnvironment(HEnvironment* outer, pop_count_(0), push_count_(0), ast_id_(BailoutId::None()), - previous_ast_id_(BailoutId::None()), zone_(zone) { } |