| Index: src/hydrogen.cc
|
| diff --git a/src/hydrogen.cc b/src/hydrogen.cc
|
| index 09e3fe9c47310195bc269cc6fa55da7dd9c44acf..acd2f349c06aad76a73dc5ccb32ee7529d47842d 100644
|
| --- a/src/hydrogen.cc
|
| +++ b/src/hydrogen.cc
|
| @@ -183,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;
|
|
|
| @@ -192,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);
|
| }
|
| @@ -640,27 +642,26 @@ DEFINE_GET_CONSTANT(Hole, the_hole, HType::Tagged(), false)
|
| #undef DEFINE_GET_CONSTANT
|
|
|
|
|
| -HGraphBuilder::CheckBuilder::CheckBuilder(HGraphBuilder* builder, BailoutId id)
|
| +HGraphBuilder::CheckBuilder::CheckBuilder(HGraphBuilder* builder)
|
| : builder_(builder),
|
| - finished_(false),
|
| - id_(id) {
|
| + finished_(false) {
|
| HEnvironment* env = builder->environment();
|
| - failure_block_ = builder->CreateBasicBlock(env->CopyWithoutHistory());
|
| - merge_block_ = builder->CreateBasicBlock(env->CopyWithoutHistory());
|
| + 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());
|
| - HBasicBlock* failure_block =
|
| - builder_->CreateBasicBlock(env->CopyWithoutHistory());
|
| + 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;
|
| @@ -674,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());
|
| - HBasicBlock* failure_block =
|
| - builder_->CreateBasicBlock(env->CopyWithoutHistory());
|
| + 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;
|
| @@ -695,11 +694,11 @@ HValue* HGraphBuilder::CheckBuilder::CheckIntegerEq(HValue* left,
|
|
|
| void HGraphBuilder::CheckBuilder::End() {
|
| ASSERT(!finished_);
|
| - builder_->current_block()->Goto(merge_block_);
|
| - failure_block_->FinishExitWithDeoptimization(HDeoptimize::kUseAll);
|
| - failure_block_->SetJoinId(id_);
|
| + 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;
|
| }
|
|
|
| @@ -709,11 +708,19 @@ HConstant* HGraph::GetInvalidContext() {
|
| }
|
|
|
|
|
| - HGraphBuilder::IfBuilder::IfBuilder(HGraphBuilder* builder, BailoutId id)
|
| +HGraphBuilder::IfBuilder::IfBuilder(HGraphBuilder* builder, int position)
|
| : builder_(builder),
|
| + position_(position),
|
| finished_(false),
|
| + did_then_(false),
|
| did_else_(false),
|
| - id_(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());
|
| last_true_block_ = NULL;
|
| @@ -721,7 +728,31 @@ HConstant* HGraph::GetInvalidContext() {
|
| }
|
|
|
|
|
| -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,
|
| @@ -731,70 +762,158 @@ 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_);
|
| - return compare;
|
| + 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::BeginElse() {
|
| +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_);
|
| +}
|
| +
|
| +
|
| +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);
|
| - 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;
|
| }
|
|
|
|
|
| HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder,
|
| HValue* context,
|
| - LoopBuilder::Direction direction,
|
| - BailoutId id)
|
| + LoopBuilder::Direction direction)
|
| : builder_(builder),
|
| context_(context),
|
| direction_(direction),
|
| - id_(id),
|
| finished_(false) {
|
| header_block_ = builder->CreateLoopHeaderBlock();
|
| body_block_ = NULL;
|
| @@ -813,7 +932,7 @@ 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();
|
| @@ -867,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
|
| @@ -904,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_ast_id(id);
|
| }
|
|
|
|
|
| @@ -955,6 +1072,21 @@ HBasicBlock* HGraphBuilder::CreateLoopHeaderBlock() {
|
| }
|
|
|
|
|
| +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,18 +1181,19 @@ HValue* HGraphBuilder::BuildCheckForCapacityGrow(HValue* object,
|
| HValue* length,
|
| HValue* key,
|
| bool is_js_array) {
|
| - BailoutId ast_id = environment()->ast_id();
|
| Zone* zone = this->zone();
|
| - IfBuilder length_checker(this, ast_id);
|
| + 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, ast_id);
|
| + 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();
|
|
|
| @@ -1069,10 +1202,10 @@ HValue* HGraphBuilder::BuildCheckForCapacityGrow(HValue* object,
|
|
|
| HValue* new_elements = BuildGrowElementsCapacity(object, elements,
|
| kind, length,
|
| - new_capacity, ast_id);
|
| + new_capacity);
|
|
|
| environment()->Push(new_elements);
|
| - capacity_checker.BeginElse();
|
| + capacity_checker.Else();
|
|
|
| environment()->Push(elements);
|
| capacity_checker.End();
|
| @@ -1092,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);
|
| @@ -1107,25 +1240,24 @@ HValue* HGraphBuilder::BuildCopyElementsOnWrite(HValue* object,
|
| HValue* elements,
|
| ElementsKind kind,
|
| HValue* length) {
|
| - BailoutId ast_id = environment()->ast_id();
|
| Zone* zone = this->zone();
|
| Heap* heap = isolate()->heap();
|
|
|
| - IfBuilder cow_checker(this, ast_id);
|
| + 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, ast_id);
|
| + kind, length, capacity);
|
|
|
| environment()->Push(new_elements);
|
|
|
| - cow_checker.BeginElse();
|
| + cow_checker.Else();
|
|
|
| environment()->Push(elements);
|
|
|
| @@ -1180,14 +1312,14 @@ 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);
|
| - BailoutId previous_id = environment()->ast_id();
|
| - ASSERT(!previous_id.IsNone());
|
| - IfBuilder length_checker(this, previous_id);
|
| - length_checker.BeginIf(key, length, Token::LT);
|
| - CheckBuilder negative_checker(this, previous_id);
|
| + IfBuilder length_checker(this);
|
| + 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);
|
| negative_checker.End();
|
| @@ -1250,8 +1382,7 @@ HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
|
|
|
| HValue* HGraphBuilder::BuildAllocateElements(HValue* context,
|
| ElementsKind kind,
|
| - HValue* capacity,
|
| - BailoutId ast_id) {
|
| + HValue* capacity) {
|
| Zone* zone = this->zone();
|
|
|
| int elements_size = IsFastDoubleElementsKind(kind)
|
| @@ -1315,9 +1446,7 @@ void HGraphBuilder::BuildInitializeElements(HValue* elements,
|
| HValue* HGraphBuilder::BuildAllocateAndInitializeElements(HValue* context,
|
| ElementsKind kind,
|
| HValue* capacity) {
|
| - BailoutId ast_id = environment()->ast_id();
|
| - HValue* new_elements =
|
| - BuildAllocateElements(context, kind, capacity, ast_id);
|
| + HValue* new_elements = BuildAllocateElements(context, kind, capacity);
|
| BuildInitializeElements(new_elements, kind, capacity);
|
| return new_elements;
|
| }
|
| @@ -1394,8 +1523,7 @@ HValue* HGraphBuilder::BuildGrowElementsCapacity(HValue* object,
|
| HValue* elements,
|
| ElementsKind kind,
|
| HValue* length,
|
| - HValue* new_capacity,
|
| - BailoutId ast_id) {
|
| + HValue* new_capacity) {
|
| Zone* zone = this->zone();
|
| HValue* context = environment()->LookupContext();
|
|
|
| @@ -1406,7 +1534,7 @@ HValue* HGraphBuilder::BuildGrowElementsCapacity(HValue* object,
|
|
|
| BuildCopyElements(context, elements, kind,
|
| new_elements, kind,
|
| - length, new_capacity, ast_id);
|
| + length, new_capacity);
|
|
|
| Factory* factory = isolate()->factory();
|
| HInstruction* elements_store = AddInstruction(new(zone) HStoreNamedField(
|
| @@ -1424,8 +1552,7 @@ void HGraphBuilder::BuildFillElementsWithHole(HValue* context,
|
| HValue* elements,
|
| ElementsKind elements_kind,
|
| HValue* from,
|
| - HValue* to,
|
| - BailoutId ast_id) {
|
| + HValue* to) {
|
| // Fast elements kinds need to be initialized in case statements below cause
|
| // a garbage collection.
|
| Factory* factory = isolate()->factory();
|
| @@ -1438,7 +1565,7 @@ void HGraphBuilder::BuildFillElementsWithHole(HValue* context,
|
| : AddInstruction(new(zone) HConstant(nan_double,
|
| Representation::Double()));
|
|
|
| - LoopBuilder builder(this, context, LoopBuilder::kPostIncrement, ast_id);
|
| + LoopBuilder builder(this, context, LoopBuilder::kPostIncrement);
|
|
|
| HValue* key = builder.BeginBody(from, to, Token::LT);
|
|
|
| @@ -1454,8 +1581,7 @@ void HGraphBuilder::BuildCopyElements(HValue* context,
|
| HValue* to_elements,
|
| ElementsKind to_elements_kind,
|
| HValue* length,
|
| - HValue* capacity,
|
| - BailoutId ast_id) {
|
| + HValue* capacity) {
|
| bool pre_fill_with_holes =
|
| IsFastDoubleElementsKind(from_elements_kind) &&
|
| IsFastObjectElementsKind(to_elements_kind);
|
| @@ -1465,10 +1591,10 @@ void HGraphBuilder::BuildCopyElements(HValue* context,
|
| // pre-initialized with holes to make sure that it's always in a consistent
|
| // state.
|
| BuildFillElementsWithHole(context, to_elements, to_elements_kind,
|
| - graph()->GetConstant0(), capacity, ast_id);
|
| + graph()->GetConstant0(), capacity);
|
| }
|
|
|
| - LoopBuilder builder(this, context, LoopBuilder::kPostIncrement, ast_id);
|
| + LoopBuilder builder(this, context, LoopBuilder::kPostIncrement);
|
|
|
| HValue* key = builder.BeginBody(graph()->GetConstant0(), length, Token::LT);
|
|
|
| @@ -1485,7 +1611,7 @@ void HGraphBuilder::BuildCopyElements(HValue* context,
|
| if (!pre_fill_with_holes && length != capacity) {
|
| // Fill unused capacity with the hole.
|
| BuildFillElementsWithHole(context, to_elements, to_elements_kind,
|
| - key, capacity, ast_id);
|
| + key, capacity);
|
| }
|
| }
|
|
|
| @@ -4111,6 +4237,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)) {
|
| @@ -4144,6 +4286,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();
|
| @@ -4172,6 +4337,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
|
| @@ -6815,7 +6995,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());
|
| }
|
|
|