| Index: src/hydrogen.cc
|
| diff --git a/src/hydrogen.cc b/src/hydrogen.cc
|
| index 99687caf91e9963727301762e6ce2d2f61af1974..77dab3dd7880dc9307d321187747395629fc666b 100644
|
| --- a/src/hydrogen.cc
|
| +++ b/src/hydrogen.cc
|
| @@ -30,6 +30,7 @@
|
| #include <algorithm>
|
|
|
| #include "v8.h"
|
| +#include "allocation-site-scopes.h"
|
| #include "codegen.h"
|
| #include "full-codegen.h"
|
| #include "hashmap.h"
|
| @@ -139,16 +140,25 @@ void HBasicBlock::RemovePhi(HPhi* phi) {
|
| }
|
|
|
|
|
| -void HBasicBlock::AddInstruction(HInstruction* instr) {
|
| +void HBasicBlock::AddInstruction(HInstruction* instr, int position) {
|
| ASSERT(!IsStartBlock() || !IsFinished());
|
| ASSERT(!instr->IsLinked());
|
| ASSERT(!IsFinished());
|
|
|
| + if (position != RelocInfo::kNoPosition) {
|
| + instr->set_position(position);
|
| + }
|
| if (first_ == NULL) {
|
| ASSERT(last_environment() != NULL);
|
| ASSERT(!last_environment()->ast_id().IsNone());
|
| HBlockEntry* entry = new(zone()) HBlockEntry();
|
| entry->InitializeAsFirst(this);
|
| + if (position != RelocInfo::kNoPosition) {
|
| + entry->set_position(position);
|
| + } else {
|
| + ASSERT(!FLAG_emit_opt_code_positions ||
|
| + !graph()->info()->IsOptimizing());
|
| + }
|
| first_ = last_ = entry;
|
| }
|
| instr->InsertAfter(last_);
|
| @@ -199,9 +209,9 @@ HSimulate* HBasicBlock::CreateSimulate(BailoutId ast_id,
|
| }
|
|
|
|
|
| -void HBasicBlock::Finish(HControlInstruction* end) {
|
| +void HBasicBlock::Finish(HControlInstruction* end, int position) {
|
| ASSERT(!IsFinished());
|
| - AddInstruction(end);
|
| + AddInstruction(end, position);
|
| end_ = end;
|
| for (HSuccessorIterator it(end); !it.Done(); it.Advance()) {
|
| it.Current()->RegisterPredecessor(this);
|
| @@ -210,6 +220,7 @@ void HBasicBlock::Finish(HControlInstruction* end) {
|
|
|
|
|
| void HBasicBlock::Goto(HBasicBlock* block,
|
| + int position,
|
| FunctionState* state,
|
| bool add_simulate) {
|
| bool drop_extra = state != NULL &&
|
| @@ -218,18 +229,21 @@ void HBasicBlock::Goto(HBasicBlock* block,
|
| if (block->IsInlineReturnTarget()) {
|
| HEnvironment* env = last_environment();
|
| int argument_count = env->arguments_environment()->parameter_count();
|
| - AddInstruction(new(zone()) HLeaveInlined(state->entry(), argument_count));
|
| + AddInstruction(new(zone())
|
| + HLeaveInlined(state->entry(), argument_count),
|
| + position);
|
| UpdateEnvironment(last_environment()->DiscardInlined(drop_extra));
|
| }
|
|
|
| - if (add_simulate) AddNewSimulate(BailoutId::None());
|
| + if (add_simulate) AddNewSimulate(BailoutId::None(), position);
|
| HGoto* instr = new(zone()) HGoto(block);
|
| - Finish(instr);
|
| + Finish(instr, position);
|
| }
|
|
|
|
|
| void HBasicBlock::AddLeaveInlined(HValue* return_value,
|
| - FunctionState* state) {
|
| + FunctionState* state,
|
| + int position) {
|
| HBasicBlock* target = state->function_return();
|
| bool drop_extra = state->inlining_kind() == DROP_EXTRA_ON_RETURN;
|
|
|
| @@ -237,12 +251,13 @@ void HBasicBlock::AddLeaveInlined(HValue* return_value,
|
| ASSERT(return_value != NULL);
|
| HEnvironment* env = last_environment();
|
| int argument_count = env->arguments_environment()->parameter_count();
|
| - AddInstruction(new(zone()) HLeaveInlined(state->entry(), argument_count));
|
| + AddInstruction(new(zone()) HLeaveInlined(state->entry(), argument_count),
|
| + position);
|
| UpdateEnvironment(last_environment()->DiscardInlined(drop_extra));
|
| last_environment()->Push(return_value);
|
| - AddNewSimulate(BailoutId::None());
|
| + AddNewSimulate(BailoutId::None(), position);
|
| HGoto* instr = new(zone()) HGoto(target);
|
| - Finish(instr);
|
| + Finish(instr, position);
|
| }
|
|
|
|
|
| @@ -633,10 +648,21 @@ HConstant* HGraph::GetConstant(SetOncePointer<HConstant>* pointer,
|
| // Can't pass GetInvalidContext() to HConstant::New, because that will
|
| // recursively call GetConstant
|
| HConstant* constant = HConstant::New(zone(), NULL, value);
|
| - constant->InsertAfter(GetConstantUndefined());
|
| + constant->InsertAfter(entry_block()->first());
|
| pointer->set(constant);
|
| + return constant;
|
| }
|
| - return pointer->get();
|
| + return ReinsertConstantIfNecessary(pointer->get());
|
| +}
|
| +
|
| +
|
| +HConstant* HGraph::ReinsertConstantIfNecessary(HConstant* constant) {
|
| + if (!constant->IsLinked()) {
|
| + // The constant was removed from the graph. Reinsert.
|
| + constant->ClearFlag(HValue::kIsDead);
|
| + constant->InsertAfter(entry_block()->first());
|
| + }
|
| + return constant;
|
| }
|
|
|
|
|
| @@ -666,13 +692,14 @@ HConstant* HGraph::GetConstant##Name() { \
|
| true, \
|
| false, \
|
| boolean_value); \
|
| - constant->InsertAfter(GetConstantUndefined()); \
|
| + constant->InsertAfter(entry_block()->first()); \
|
| constant_##name##_.set(constant); \
|
| } \
|
| - return constant_##name##_.get(); \
|
| + return ReinsertConstantIfNecessary(constant_##name##_.get()); \
|
| }
|
|
|
|
|
| +DEFINE_GET_CONSTANT(Undefined, undefined, HType::Tagged(), false)
|
| DEFINE_GET_CONSTANT(True, true, HType::Boolean(), true)
|
| DEFINE_GET_CONSTANT(False, false, HType::Boolean(), false)
|
| DEFINE_GET_CONSTANT(Hole, the_hole, HType::Tagged(), false)
|
| @@ -700,9 +727,8 @@ bool HGraph::IsStandardConstant(HConstant* constant) {
|
| }
|
|
|
|
|
| -HGraphBuilder::IfBuilder::IfBuilder(HGraphBuilder* builder, int position)
|
| +HGraphBuilder::IfBuilder::IfBuilder(HGraphBuilder* builder)
|
| : builder_(builder),
|
| - position_(position),
|
| finished_(false),
|
| deopt_then_(false),
|
| deopt_else_(false),
|
| @@ -725,7 +751,6 @@ HGraphBuilder::IfBuilder::IfBuilder(
|
| HGraphBuilder* builder,
|
| HIfContinuation* continuation)
|
| : builder_(builder),
|
| - position_(RelocInfo::kNoPosition),
|
| finished_(false),
|
| deopt_then_(false),
|
| deopt_else_(false),
|
| @@ -741,8 +766,7 @@ HGraphBuilder::IfBuilder::IfBuilder(
|
| split_edge_merge_block_(NULL),
|
| merge_block_(NULL) {
|
| continuation->Continue(&first_true_block_,
|
| - &first_false_block_,
|
| - &position_);
|
| + &first_false_block_);
|
| }
|
|
|
|
|
| @@ -759,25 +783,26 @@ HControlInstruction* HGraphBuilder::IfBuilder::AddCompare(
|
| compare->SetSuccessorAt(0, first_true_block_);
|
| compare->SetSuccessorAt(1, split_edge);
|
| }
|
| - split_edge->GotoNoSimulate(split_edge_merge_block_);
|
| + builder_->GotoNoSimulate(split_edge, split_edge_merge_block_);
|
| } else {
|
| compare->SetSuccessorAt(0, first_true_block_);
|
| compare->SetSuccessorAt(1, first_false_block_);
|
| }
|
| - builder_->current_block()->Finish(compare);
|
| + builder_->FinishCurrentBlock(compare);
|
| needs_compare_ = false;
|
| return compare;
|
| }
|
|
|
|
|
| void HGraphBuilder::IfBuilder::Or() {
|
| + ASSERT(!needs_compare_);
|
| 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_);
|
| + builder_->GotoNoSimulate(first_true_block_, split_edge_merge_block_);
|
| first_true_block_ = split_edge_merge_block_;
|
| }
|
| builder_->set_current_block(first_false_block_);
|
| @@ -786,12 +811,13 @@ void HGraphBuilder::IfBuilder::Or() {
|
|
|
|
|
| void HGraphBuilder::IfBuilder::And() {
|
| + ASSERT(!needs_compare_);
|
| 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_);
|
| + builder_->GotoNoSimulate(first_false_block_, split_edge_merge_block_);
|
| first_false_block_ = split_edge_merge_block_;
|
| }
|
| builder_->set_current_block(first_true_block_);
|
| @@ -809,7 +835,7 @@ void HGraphBuilder::IfBuilder::CaptureContinuation(
|
| HBasicBlock* false_block = did_else_ && (first_false_block_ != NULL)
|
| ? builder_->current_block()
|
| : first_false_block_;
|
| - continuation->Capture(true_block, false_block, position_);
|
| + continuation->Capture(true_block, false_block);
|
| captured_ = true;
|
| End();
|
| }
|
| @@ -826,11 +852,11 @@ void HGraphBuilder::IfBuilder::JoinContinuation(HIfContinuation* continuation) {
|
| : first_false_block_;
|
| if (true_block != NULL && !true_block->IsFinished()) {
|
| ASSERT(continuation->IsTrueReachable());
|
| - true_block->GotoNoSimulate(continuation->true_branch());
|
| + builder_->GotoNoSimulate(true_block, continuation->true_branch());
|
| }
|
| if (false_block != NULL && !false_block->IsFinished()) {
|
| ASSERT(continuation->IsFalseReachable());
|
| - false_block->GotoNoSimulate(continuation->false_branch());
|
| + builder_->GotoNoSimulate(false_block, continuation->false_branch());
|
| }
|
| captured_ = true;
|
| End();
|
| @@ -851,7 +877,7 @@ void HGraphBuilder::IfBuilder::Then() {
|
| boolean_type.Add(ToBooleanStub::BOOLEAN);
|
| HBranch* branch = builder()->New<HBranch>(
|
| constant_false, boolean_type, first_true_block_, first_false_block_);
|
| - builder_->current_block()->Finish(branch);
|
| + builder_->FinishCurrentBlock(branch);
|
| }
|
| builder_->set_current_block(first_true_block_);
|
| }
|
| @@ -879,10 +905,9 @@ void HGraphBuilder::IfBuilder::Deopt(const char* reason) {
|
|
|
|
|
| void HGraphBuilder::IfBuilder::Return(HValue* value) {
|
| - HBasicBlock* block = builder_->current_block();
|
| HValue* parameter_count = builder_->graph()->GetConstantMinus1();
|
| - block->FinishExit(builder_->New<HReturn>(value, parameter_count));
|
| - builder_->set_current_block(NULL);
|
| + builder_->FinishExitCurrentBlock(
|
| + builder_->New<HReturn>(value, parameter_count));
|
| if (did_else_) {
|
| first_false_block_ = NULL;
|
| } else {
|
| @@ -912,17 +937,17 @@ void HGraphBuilder::IfBuilder::End() {
|
| HBasicBlock* last_false_block = builder_->current_block();
|
| ASSERT(!last_false_block->IsFinished());
|
| if (deopt_then_) {
|
| - last_false_block->GotoNoSimulate(merge_block_);
|
| + builder_->GotoNoSimulate(last_false_block, merge_block_);
|
| builder_->PadEnvironmentForContinuation(last_true_block_,
|
| merge_block_);
|
| - last_true_block_->GotoNoSimulate(merge_block_);
|
| + builder_->GotoNoSimulate(last_true_block_, merge_block_);
|
| } else {
|
| - last_true_block_->GotoNoSimulate(merge_block_);
|
| + builder_->GotoNoSimulate(last_true_block_, merge_block_);
|
| if (deopt_else_) {
|
| builder_->PadEnvironmentForContinuation(last_false_block,
|
| merge_block_);
|
| }
|
| - last_false_block->GotoNoSimulate(merge_block_);
|
| + builder_->GotoNoSimulate(last_false_block, merge_block_);
|
| }
|
| builder_->set_current_block(merge_block_);
|
| }
|
| @@ -970,7 +995,7 @@ HValue* HGraphBuilder::LoopBuilder::BeginBody(
|
| phi_ = header_block_->AddNewPhi(env->values()->length());
|
| phi_->AddInput(initial);
|
| env->Push(initial);
|
| - builder_->current_block()->GotoNoSimulate(header_block_);
|
| + builder_->GotoNoSimulate(header_block_);
|
|
|
| HEnvironment* body_env = env->Copy();
|
| HEnvironment* exit_env = env->Copy();
|
| @@ -982,7 +1007,7 @@ HValue* HGraphBuilder::LoopBuilder::BeginBody(
|
|
|
| builder_->set_current_block(header_block_);
|
| env->Pop();
|
| - builder_->current_block()->Finish(builder_->New<HCompareNumericAndBranch>(
|
| + builder_->FinishCurrentBlock(builder_->New<HCompareNumericAndBranch>(
|
| phi_, terminating, token, body_block_, exit_block_));
|
|
|
| builder_->set_current_block(body_block_);
|
| @@ -1007,10 +1032,10 @@ void HGraphBuilder::LoopBuilder::Break() {
|
| // Its the first time we saw a break.
|
| HEnvironment* env = exit_block_->last_environment()->Copy();
|
| exit_trampoline_block_ = builder_->CreateBasicBlock(env);
|
| - exit_block_->GotoNoSimulate(exit_trampoline_block_);
|
| + builder_->GotoNoSimulate(exit_block_, exit_trampoline_block_);
|
| }
|
|
|
| - builder_->current_block()->GotoNoSimulate(exit_trampoline_block_);
|
| + builder_->GotoNoSimulate(exit_trampoline_block_);
|
| }
|
|
|
|
|
| @@ -1030,7 +1055,7 @@ void HGraphBuilder::LoopBuilder::EndBody() {
|
| // Push the new increment value on the expression stack to merge into the phi.
|
| builder_->environment()->Push(increment_);
|
| HBasicBlock* last_block = builder_->current_block();
|
| - last_block->GotoNoSimulate(header_block_);
|
| + builder_->GotoNoSimulate(last_block, header_block_);
|
| header_block_->loop_information()->RegisterBackEdge(last_block);
|
|
|
| if (exit_trampoline_block_ != NULL) {
|
| @@ -1055,7 +1080,9 @@ HGraph* HGraphBuilder::CreateGraph() {
|
|
|
| HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) {
|
| ASSERT(current_block() != NULL);
|
| - current_block()->AddInstruction(instr);
|
| + ASSERT(!FLAG_emit_opt_code_positions ||
|
| + position_ != RelocInfo::kNoPosition || !info_->IsOptimizing());
|
| + current_block()->AddInstruction(instr, position_);
|
| if (graph()->IsInsideNoSideEffectsScope()) {
|
| instr->SetFlag(HValue::kHasNoObservableSideEffects);
|
| }
|
| @@ -1063,6 +1090,26 @@ HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) {
|
| }
|
|
|
|
|
| +void HGraphBuilder::FinishCurrentBlock(HControlInstruction* last) {
|
| + ASSERT(!FLAG_emit_opt_code_positions || !info_->IsOptimizing() ||
|
| + position_ != RelocInfo::kNoPosition);
|
| + current_block()->Finish(last, position_);
|
| + if (last->IsReturn() || last->IsAbnormalExit()) {
|
| + set_current_block(NULL);
|
| + }
|
| +}
|
| +
|
| +
|
| +void HGraphBuilder::FinishExitCurrentBlock(HControlInstruction* instruction) {
|
| + ASSERT(!FLAG_emit_opt_code_positions || !info_->IsOptimizing() ||
|
| + position_ != RelocInfo::kNoPosition);
|
| + current_block()->FinishExit(instruction, position_);
|
| + if (instruction->IsReturn() || instruction->IsAbnormalExit()) {
|
| + set_current_block(NULL);
|
| + }
|
| +}
|
| +
|
| +
|
| void HGraphBuilder::AddIncrementCounter(StatsCounter* counter) {
|
| if (FLAG_native_code_counters && counter->Enabled()) {
|
| HValue* reference = Add<HConstant>(ExternalReference(counter));
|
| @@ -1111,9 +1158,9 @@ void HGraphBuilder::FinishExitWithHardDeoptimization(
|
| PadEnvironmentForContinuation(current_block(), continuation);
|
| Add<HDeoptimize>(reason, Deoptimizer::EAGER);
|
| if (graph()->IsInsideNoSideEffectsScope()) {
|
| - current_block()->GotoNoSimulate(continuation);
|
| + GotoNoSimulate(continuation);
|
| } else {
|
| - current_block()->Goto(continuation);
|
| + Goto(continuation);
|
| }
|
| }
|
|
|
| @@ -1158,7 +1205,6 @@ HValue* HGraphBuilder::BuildCheckForCapacityGrow(HValue* object,
|
| HValue* length,
|
| HValue* key,
|
| bool is_js_array) {
|
| - Zone* zone = this->zone();
|
| IfBuilder length_checker(this);
|
|
|
| Token::Value token = IsHoleyElementsKind(kind) ? Token::GTE : Token::EQ;
|
| @@ -1174,8 +1220,6 @@ HValue* HGraphBuilder::BuildCheckForCapacityGrow(HValue* object,
|
| Token::GTE);
|
| capacity_checker.Then();
|
|
|
| - HValue* context = environment()->context();
|
| -
|
| HValue* max_gap = Add<HConstant>(static_cast<int32_t>(JSObject::kMaxGap));
|
| HValue* max_capacity = Add<HAdd>(current_capacity, max_gap);
|
| IfBuilder key_checker(this);
|
| @@ -1196,8 +1240,7 @@ HValue* HGraphBuilder::BuildCheckForCapacityGrow(HValue* object,
|
| capacity_checker.End();
|
|
|
| if (is_js_array) {
|
| - HValue* new_length = AddInstruction(
|
| - HAdd::New(zone, context, key, graph_->GetConstant1()));
|
| + HValue* new_length = AddUncasted<HAdd>(key, graph_->GetConstant1());
|
| new_length->ClearFlag(HValue::kCanOverflow);
|
|
|
| Add<HStoreNamedField>(object, HObjectAccess::ForArrayLength(kind),
|
| @@ -1282,9 +1325,10 @@ void HGraphBuilder::BuildTransitionElementsKind(HValue* object,
|
| }
|
|
|
|
|
| -HValue* HGraphBuilder::BuildLookupNumberStringCache(
|
| - HValue* object,
|
| - HIfContinuation* continuation) {
|
| +HValue* HGraphBuilder::BuildNumberToString(HValue* object,
|
| + Handle<Type> type) {
|
| + NoObservableSideEffectsScope scope(this);
|
| +
|
| // Create a joinable continuation.
|
| HIfContinuation found(graph()->CreateBasicBlock(),
|
| graph()->CreateBasicBlock());
|
| @@ -1293,7 +1337,7 @@ HValue* HGraphBuilder::BuildLookupNumberStringCache(
|
| HValue* number_string_cache =
|
| Add<HLoadRoot>(Heap::kNumberStringCacheRootIndex);
|
|
|
| - // Make the hash maks from the length of the number string cache. It
|
| + // Make the hash mask from the length of the number string cache. It
|
| // contains two elements (number and string) for each cache entry.
|
| HValue* mask = AddLoadFixedArrayLength(number_string_cache);
|
| mask->set_type(HType::Smi());
|
| @@ -1310,13 +1354,13 @@ HValue* HGraphBuilder::BuildLookupNumberStringCache(
|
|
|
| // Load the key.
|
| HValue* key_index = Add<HShl>(hash, graph()->GetConstant1());
|
| - HValue* key = AddFastElementAccess(number_string_cache, key_index,
|
| - NULL, NULL, FAST_ELEMENTS, false,
|
| - ALLOW_RETURN_HOLE, STANDARD_STORE);
|
| + HValue* key = Add<HLoadKeyed>(number_string_cache, key_index,
|
| + static_cast<HValue*>(NULL),
|
| + FAST_ELEMENTS, ALLOW_RETURN_HOLE);
|
|
|
| // Check if object == key.
|
| IfBuilder if_objectiskey(this);
|
| - if_objectiskey.If<HCompareObjectEqAndBranch>(key, object);
|
| + if_objectiskey.If<HCompareObjectEqAndBranch>(object, key);
|
| if_objectiskey.Then();
|
| {
|
| // Make the key_index available.
|
| @@ -1326,92 +1370,84 @@ HValue* HGraphBuilder::BuildLookupNumberStringCache(
|
| }
|
| if_objectissmi.Else();
|
| {
|
| - // Check if object is a heap number.
|
| - IfBuilder if_objectisnumber(this);
|
| - if_objectisnumber.If<HCompareMap>(
|
| - object, isolate()->factory()->heap_number_map());
|
| - if_objectisnumber.Then();
|
| - {
|
| - // Compute hash for heap number similar to double_get_hash().
|
| - HValue* low = Add<HLoadNamedField>(
|
| - object, HObjectAccess::ForHeapNumberValueLowestBits());
|
| - HValue* high = Add<HLoadNamedField>(
|
| - object, HObjectAccess::ForHeapNumberValueHighestBits());
|
| - HValue* hash = Add<HBitwise>(Token::BIT_XOR, low, high);
|
| - hash = Add<HBitwise>(Token::BIT_AND, hash, mask);
|
| -
|
| - // Load the key.
|
| - HValue* key_index = Add<HShl>(hash, graph()->GetConstant1());
|
| - HValue* key = AddFastElementAccess(number_string_cache, key_index,
|
| - NULL, NULL, FAST_ELEMENTS, false,
|
| - ALLOW_RETURN_HOLE, STANDARD_STORE);
|
| -
|
| - // Check if key is a heap number.
|
| - IfBuilder if_keyisnumber(this);
|
| - if_keyisnumber.IfNot<HIsSmiAndBranch>(key);
|
| - if_keyisnumber.AndIf<HCompareMap>(
|
| - key, isolate()->factory()->heap_number_map());
|
| - if_keyisnumber.Then();
|
| + if (type->Is(Type::Smi())) {
|
| + if_objectissmi.Deopt("Excepted smi");
|
| + } else {
|
| + // Check if the object is a heap number.
|
| + IfBuilder if_objectisnumber(this);
|
| + if_objectisnumber.If<HCompareMap>(
|
| + object, isolate()->factory()->heap_number_map());
|
| + if_objectisnumber.Then();
|
| {
|
| - // Check if values of key and object match.
|
| - IfBuilder if_keyeqobject(this);
|
| - if_keyeqobject.If<HCompareNumericAndBranch>(
|
| - Add<HLoadNamedField>(key, HObjectAccess::ForHeapNumberValue()),
|
| - Add<HLoadNamedField>(object, HObjectAccess::ForHeapNumberValue()),
|
| - Token::EQ);
|
| - if_keyeqobject.Then();
|
| + // Compute hash for heap number similar to double_get_hash().
|
| + HValue* low = Add<HLoadNamedField>(
|
| + object, HObjectAccess::ForHeapNumberValueLowestBits());
|
| + HValue* high = Add<HLoadNamedField>(
|
| + object, HObjectAccess::ForHeapNumberValueHighestBits());
|
| + HValue* hash = Add<HBitwise>(Token::BIT_XOR, low, high);
|
| + hash = Add<HBitwise>(Token::BIT_AND, hash, mask);
|
| +
|
| + // Load the key.
|
| + HValue* key_index = Add<HShl>(hash, graph()->GetConstant1());
|
| + HValue* key = Add<HLoadKeyed>(number_string_cache, key_index,
|
| + static_cast<HValue*>(NULL),
|
| + FAST_ELEMENTS, ALLOW_RETURN_HOLE);
|
| +
|
| + // Check if key is a heap number (the number string cache contains only
|
| + // SMIs and heap number, so it is sufficient to do a SMI check here).
|
| + IfBuilder if_keyisnotsmi(this);
|
| + if_keyisnotsmi.IfNot<HIsSmiAndBranch>(key);
|
| + if_keyisnotsmi.Then();
|
| {
|
| - // Make the key_index available.
|
| - Push(key_index);
|
| + // Check if values of key and object match.
|
| + IfBuilder if_keyeqobject(this);
|
| + if_keyeqobject.If<HCompareNumericAndBranch>(
|
| + Add<HLoadNamedField>(key, HObjectAccess::ForHeapNumberValue()),
|
| + Add<HLoadNamedField>(object, HObjectAccess::ForHeapNumberValue()),
|
| + Token::EQ);
|
| + if_keyeqobject.Then();
|
| + {
|
| + // Make the key_index available.
|
| + Push(key_index);
|
| + }
|
| + if_keyeqobject.JoinContinuation(&found);
|
| }
|
| - if_keyeqobject.JoinContinuation(&found);
|
| + if_keyisnotsmi.JoinContinuation(&found);
|
| }
|
| - if_keyisnumber.JoinContinuation(&found);
|
| + if_objectisnumber.Else();
|
| + {
|
| + if (type->Is(Type::Number())) {
|
| + if_objectisnumber.Deopt("Expected heap number");
|
| + }
|
| + }
|
| + if_objectisnumber.JoinContinuation(&found);
|
| }
|
| - if_objectisnumber.JoinContinuation(&found);
|
| }
|
| - if_objectissmi.End();
|
| + if_objectissmi.JoinContinuation(&found);
|
|
|
| // Check for cache hit.
|
| IfBuilder if_found(this, &found);
|
| if_found.Then();
|
| + {
|
| + // Count number to string operation in native code.
|
| + AddIncrementCounter(isolate()->counters()->number_to_string_native());
|
|
|
| - // Load the value in case of cache hit.
|
| - HValue* key_index = Pop();
|
| - HValue* value_index = Add<HAdd>(key_index, graph()->GetConstant1());
|
| - HValue* value = AddFastElementAccess(number_string_cache, value_index,
|
| - NULL, NULL, FAST_ELEMENTS, false,
|
| - ALLOW_RETURN_HOLE, STANDARD_STORE);
|
| - AddIncrementCounter(isolate()->counters()->number_to_string_native());
|
| -
|
| - if_found.CaptureContinuation(continuation);
|
| -
|
| - // The value is only available in true branch of continuation.
|
| - return value;
|
| -}
|
| -
|
| -
|
| -HValue* HGraphBuilder::BuildNumberToString(HValue* number) {
|
| - NoObservableSideEffectsScope scope(this);
|
| -
|
| - // Lookup the number in the number string cache.
|
| - HIfContinuation continuation;
|
| - HValue* value = BuildLookupNumberStringCache(number, &continuation);
|
| - IfBuilder if_found(this, &continuation);
|
| - if_found.Then();
|
| -
|
| - // Cache hit.
|
| - Push(value);
|
| -
|
| + // Load the value in case of cache hit.
|
| + HValue* key_index = Pop();
|
| + HValue* value_index = Add<HAdd>(key_index, graph()->GetConstant1());
|
| + Push(Add<HLoadKeyed>(number_string_cache, value_index,
|
| + static_cast<HValue*>(NULL),
|
| + FAST_ELEMENTS, ALLOW_RETURN_HOLE));
|
| + }
|
| if_found.Else();
|
| -
|
| - // Cache miss, fallback to runtime.
|
| - Add<HPushArgument>(number);
|
| - Push(Add<HCallRuntime>(
|
| - isolate()->factory()->empty_string(),
|
| - Runtime::FunctionForId(Runtime::kNumberToStringSkipCache),
|
| - 1));
|
| -
|
| + {
|
| + // Cache miss, fallback to runtime.
|
| + Add<HPushArgument>(object);
|
| + Push(Add<HCallRuntime>(
|
| + isolate()->factory()->empty_string(),
|
| + Runtime::FunctionForId(Runtime::kNumberToStringSkipCache),
|
| + 1));
|
| + }
|
| if_found.End();
|
|
|
| return Pop();
|
| @@ -1469,7 +1505,7 @@ HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
|
| HValue* bounds_check = negative_checker.If<HCompareNumericAndBranch>(
|
| key, graph()->GetConstant0(), Token::GTE);
|
| negative_checker.Then();
|
| - HInstruction* result = AddExternalArrayElementAccess(
|
| + HInstruction* result = AddElementAccess(
|
| external_elements, key, val, bounds_check, elements_kind, is_store);
|
| negative_checker.ElseDeopt("Negative key encountered");
|
| length_checker.End();
|
| @@ -1479,7 +1515,7 @@ HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
|
| checked_key = Add<HBoundsCheck>(key, length);
|
| HLoadExternalArrayPointer* external_elements =
|
| Add<HLoadExternalArrayPointer>(elements);
|
| - return AddExternalArrayElementAccess(
|
| + return AddElementAccess(
|
| external_elements, checked_key, val,
|
| checked_object, elements_kind, is_store);
|
| }
|
| @@ -1512,14 +1548,13 @@ HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
|
| elements_kind, length);
|
| } else {
|
| HCheckMaps* check_cow_map = Add<HCheckMaps>(
|
| - elements, isolate()->factory()->fixed_array_map(),
|
| - top_info());
|
| + elements, isolate()->factory()->fixed_array_map(), top_info());
|
| check_cow_map->ClearGVNFlag(kDependsOnElementsKind);
|
| }
|
| }
|
| }
|
| - return AddFastElementAccess(elements, checked_key, val, checked_object,
|
| - elements_kind, is_store, load_mode, store_mode);
|
| + return AddElementAccess(elements, checked_key, val, checked_object,
|
| + elements_kind, is_store, load_mode);
|
| }
|
|
|
|
|
| @@ -1609,85 +1644,31 @@ HInnerAllocatedObject* HGraphBuilder::BuildJSArrayHeader(HValue* array,
|
| }
|
|
|
|
|
| -HInstruction* HGraphBuilder::AddExternalArrayElementAccess(
|
| - HValue* external_elements,
|
| +HInstruction* HGraphBuilder::AddElementAccess(
|
| + HValue* elements,
|
| HValue* checked_key,
|
| HValue* val,
|
| HValue* dependency,
|
| ElementsKind elements_kind,
|
| - bool is_store) {
|
| + bool is_store,
|
| + LoadKeyedHoleMode load_mode) {
|
| if (is_store) {
|
| ASSERT(val != NULL);
|
| - switch (elements_kind) {
|
| - case EXTERNAL_PIXEL_ELEMENTS: {
|
| - val = Add<HClampToUint8>(val);
|
| - break;
|
| - }
|
| - case EXTERNAL_BYTE_ELEMENTS:
|
| - case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
|
| - case EXTERNAL_SHORT_ELEMENTS:
|
| - case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
|
| - case EXTERNAL_INT_ELEMENTS:
|
| - case EXTERNAL_UNSIGNED_INT_ELEMENTS: {
|
| - break;
|
| - }
|
| - case EXTERNAL_FLOAT_ELEMENTS:
|
| - case EXTERNAL_DOUBLE_ELEMENTS:
|
| - break;
|
| - case FAST_SMI_ELEMENTS:
|
| - case FAST_ELEMENTS:
|
| - case FAST_DOUBLE_ELEMENTS:
|
| - case FAST_HOLEY_SMI_ELEMENTS:
|
| - case FAST_HOLEY_ELEMENTS:
|
| - case FAST_HOLEY_DOUBLE_ELEMENTS:
|
| - case DICTIONARY_ELEMENTS:
|
| - case NON_STRICT_ARGUMENTS_ELEMENTS:
|
| - UNREACHABLE();
|
| - break;
|
| - }
|
| - return Add<HStoreKeyed>(external_elements, checked_key, val, elements_kind);
|
| - } else {
|
| - ASSERT(val == NULL);
|
| - HLoadKeyed* load = Add<HLoadKeyed>(external_elements,
|
| - checked_key,
|
| - dependency,
|
| - elements_kind);
|
| - if (FLAG_opt_safe_uint32_operations &&
|
| - elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) {
|
| - graph()->RecordUint32Instruction(load);
|
| + if (elements_kind == EXTERNAL_PIXEL_ELEMENTS) {
|
| + val = Add<HClampToUint8>(val);
|
| }
|
| - return load;
|
| + return Add<HStoreKeyed>(elements, checked_key, val, elements_kind);
|
| }
|
| -}
|
| -
|
|
|
| -HInstruction* HGraphBuilder::AddFastElementAccess(
|
| - HValue* elements,
|
| - HValue* checked_key,
|
| - HValue* val,
|
| - HValue* load_dependency,
|
| - ElementsKind elements_kind,
|
| - bool is_store,
|
| - LoadKeyedHoleMode load_mode,
|
| - KeyedAccessStoreMode store_mode) {
|
| - if (is_store) {
|
| - ASSERT(val != NULL);
|
| - switch (elements_kind) {
|
| - case FAST_SMI_ELEMENTS:
|
| - case FAST_HOLEY_SMI_ELEMENTS:
|
| - case FAST_ELEMENTS:
|
| - case FAST_HOLEY_ELEMENTS:
|
| - case FAST_DOUBLE_ELEMENTS:
|
| - case FAST_HOLEY_DOUBLE_ELEMENTS:
|
| - return Add<HStoreKeyed>(elements, checked_key, val, elements_kind);
|
| - default:
|
| - UNREACHABLE();
|
| - return NULL;
|
| - }
|
| + ASSERT(!is_store);
|
| + ASSERT(val == NULL);
|
| + HLoadKeyed* load = Add<HLoadKeyed>(
|
| + elements, checked_key, dependency, elements_kind, load_mode);
|
| + if (FLAG_opt_safe_uint32_operations &&
|
| + elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) {
|
| + graph()->RecordUint32Instruction(load);
|
| }
|
| - // It's an element load (!is_store).
|
| - return Add<HLoadKeyed>(
|
| - elements, checked_key, load_dependency, elements_kind, load_mode);
|
| + return load;
|
| }
|
|
|
|
|
| @@ -1937,9 +1918,8 @@ HValue* HGraphBuilder::BuildCloneShallowArray(HValue* boilerplate,
|
| void HGraphBuilder::BuildCompareNil(
|
| HValue* value,
|
| Handle<Type> type,
|
| - int position,
|
| HIfContinuation* continuation) {
|
| - IfBuilder if_nil(this, position);
|
| + IfBuilder if_nil(this);
|
| bool some_case_handled = false;
|
| bool some_case_missing = false;
|
|
|
| @@ -2051,8 +2031,7 @@ HValue* HGraphBuilder::JSArrayBuilder::EmitMapCode() {
|
| // No need for a context lookup if the kind_ matches the initial
|
| // map, because we can just load the map in that case.
|
| HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap();
|
| - return builder()->AddInstruction(
|
| - builder()->BuildLoadNamedField(constructor_function_, access));
|
| + return builder()->AddLoadNamedField(constructor_function_, access);
|
| }
|
|
|
| HInstruction* native_context = builder()->BuildGetNativeContext();
|
| @@ -2072,8 +2051,7 @@ HValue* HGraphBuilder::JSArrayBuilder::EmitMapCode() {
|
| HValue* HGraphBuilder::JSArrayBuilder::EmitInternalMapCode() {
|
| // Find the map near the constructor function
|
| HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap();
|
| - return builder()->AddInstruction(
|
| - builder()->BuildLoadNamedField(constructor_function_, access));
|
| + return builder()->AddLoadNamedField(constructor_function_, access);
|
| }
|
|
|
|
|
| @@ -2207,6 +2185,9 @@ HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info)
|
| // to know it's the initial state.
|
| function_state_= &initial_function_state_;
|
| InitializeAstVisitor(info->isolate());
|
| + if (FLAG_emit_opt_code_positions) {
|
| + SetSourcePosition(info->shared_info()->start_position());
|
| + }
|
| }
|
|
|
|
|
| @@ -2219,8 +2200,8 @@ HBasicBlock* HOptimizedGraphBuilder::CreateJoin(HBasicBlock* first,
|
| return first;
|
| } else {
|
| HBasicBlock* join_block = graph()->CreateBasicBlock();
|
| - first->Goto(join_block);
|
| - second->Goto(join_block);
|
| + Goto(first, join_block);
|
| + Goto(second, join_block);
|
| join_block->SetJoinId(join_id);
|
| return join_block;
|
| }
|
| @@ -2231,7 +2212,7 @@ HBasicBlock* HOptimizedGraphBuilder::JoinContinue(IterationStatement* statement,
|
| HBasicBlock* exit_block,
|
| HBasicBlock* continue_block) {
|
| if (continue_block != NULL) {
|
| - if (exit_block != NULL) exit_block->Goto(continue_block);
|
| + if (exit_block != NULL) Goto(exit_block, continue_block);
|
| continue_block->SetJoinId(statement->ContinueId());
|
| return continue_block;
|
| }
|
| @@ -2244,10 +2225,10 @@ HBasicBlock* HOptimizedGraphBuilder::CreateLoop(IterationStatement* statement,
|
| HBasicBlock* body_exit,
|
| HBasicBlock* loop_successor,
|
| HBasicBlock* break_block) {
|
| - if (body_exit != NULL) body_exit->Goto(loop_entry);
|
| + if (body_exit != NULL) Goto(body_exit, loop_entry);
|
| loop_entry->PostProcessLoopHeader(statement);
|
| if (break_block != NULL) {
|
| - if (loop_successor != NULL) loop_successor->Goto(break_block);
|
| + if (loop_successor != NULL) Goto(loop_successor, break_block);
|
| break_block->SetJoinId(statement->ExitId());
|
| return break_block;
|
| }
|
| @@ -2258,7 +2239,7 @@ HBasicBlock* HOptimizedGraphBuilder::CreateLoop(IterationStatement* statement,
|
| // Build a new loop header block and set it as the current block.
|
| HBasicBlock* HOptimizedGraphBuilder::BuildLoopEntry() {
|
| HBasicBlock* loop_entry = CreateLoopHeaderBlock();
|
| - current_block()->Goto(loop_entry);
|
| + Goto(loop_entry);
|
| set_current_block(loop_entry);
|
| return loop_entry;
|
| }
|
| @@ -2273,8 +2254,8 @@ HBasicBlock* HOptimizedGraphBuilder::BuildLoopEntry(
|
| }
|
|
|
|
|
| -void HBasicBlock::FinishExit(HControlInstruction* instruction) {
|
| - Finish(instruction);
|
| +void HBasicBlock::FinishExit(HControlInstruction* instruction, int position) {
|
| + Finish(instruction, position);
|
| ClearEnvironment();
|
| }
|
|
|
| @@ -2822,7 +2803,7 @@ void EffectContext::ReturnControl(HControlInstruction* instr,
|
| HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock();
|
| instr->SetSuccessorAt(0, empty_true);
|
| instr->SetSuccessorAt(1, empty_false);
|
| - owner()->current_block()->Finish(instr);
|
| + owner()->FinishCurrentBlock(instr);
|
| HBasicBlock* join = owner()->CreateJoin(empty_true, empty_false, ast_id);
|
| owner()->set_current_block(join);
|
| }
|
| @@ -2832,7 +2813,7 @@ void EffectContext::ReturnContinuation(HIfContinuation* continuation,
|
| BailoutId ast_id) {
|
| HBasicBlock* true_branch = NULL;
|
| HBasicBlock* false_branch = NULL;
|
| - continuation->Continue(&true_branch, &false_branch, NULL);
|
| + continuation->Continue(&true_branch, &false_branch);
|
| if (!continuation->IsTrueReachable()) {
|
| owner()->set_current_block(false_branch);
|
| } else if (!continuation->IsFalseReachable()) {
|
| @@ -2866,7 +2847,7 @@ void ValueContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) {
|
| HBasicBlock* materialize_true = owner()->graph()->CreateBasicBlock();
|
| instr->SetSuccessorAt(0, materialize_true);
|
| instr->SetSuccessorAt(1, materialize_false);
|
| - owner()->current_block()->Finish(instr);
|
| + owner()->FinishCurrentBlock(instr);
|
| owner()->set_current_block(materialize_true);
|
| owner()->Push(owner()->graph()->GetConstantTrue());
|
| owner()->set_current_block(materialize_false);
|
| @@ -2881,7 +2862,7 @@ void ValueContext::ReturnContinuation(HIfContinuation* continuation,
|
| BailoutId ast_id) {
|
| HBasicBlock* materialize_true = NULL;
|
| HBasicBlock* materialize_false = NULL;
|
| - continuation->Continue(&materialize_true, &materialize_false, NULL);
|
| + continuation->Continue(&materialize_true, &materialize_false);
|
| if (continuation->IsTrueReachable()) {
|
| owner()->set_current_block(materialize_true);
|
| owner()->Push(owner()->graph()->GetConstantTrue());
|
| @@ -2921,9 +2902,9 @@ void TestContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) {
|
| HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock();
|
| instr->SetSuccessorAt(0, empty_true);
|
| instr->SetSuccessorAt(1, empty_false);
|
| - owner()->current_block()->Finish(instr);
|
| - empty_true->Goto(if_true(), owner()->function_state());
|
| - empty_false->Goto(if_false(), owner()->function_state());
|
| + owner()->FinishCurrentBlock(instr);
|
| + owner()->Goto(empty_true, if_true(), owner()->function_state());
|
| + owner()->Goto(empty_false, if_false(), owner()->function_state());
|
| owner()->set_current_block(NULL);
|
| }
|
|
|
| @@ -2932,12 +2913,12 @@ void TestContext::ReturnContinuation(HIfContinuation* continuation,
|
| BailoutId ast_id) {
|
| HBasicBlock* true_branch = NULL;
|
| HBasicBlock* false_branch = NULL;
|
| - continuation->Continue(&true_branch, &false_branch, NULL);
|
| + continuation->Continue(&true_branch, &false_branch);
|
| if (continuation->IsTrueReachable()) {
|
| - true_branch->Goto(if_true(), owner()->function_state());
|
| + owner()->Goto(true_branch, if_true(), owner()->function_state());
|
| }
|
| if (continuation->IsFalseReachable()) {
|
| - false_branch->Goto(if_false(), owner()->function_state());
|
| + owner()->Goto(false_branch, if_false(), owner()->function_state());
|
| }
|
| owner()->set_current_block(NULL);
|
| }
|
| @@ -2955,11 +2936,11 @@ void TestContext::BuildBranch(HValue* value) {
|
| HBasicBlock* empty_true = builder->graph()->CreateBasicBlock();
|
| HBasicBlock* empty_false = builder->graph()->CreateBasicBlock();
|
| ToBooleanStub::Types expected(condition()->to_boolean_types());
|
| - builder->current_block()->Finish(builder->New<HBranch>(
|
| + builder->FinishCurrentBlock(builder->New<HBranch>(
|
| value, expected, empty_true, empty_false));
|
|
|
| - empty_true->Goto(if_true(), builder->function_state());
|
| - empty_false->Goto(if_false(), builder->function_state());
|
| + owner()->Goto(empty_true, if_true(), builder->function_state());
|
| + owner()->Goto(empty_false , if_false(), builder->function_state());
|
| builder->set_current_block(NULL);
|
| }
|
|
|
| @@ -3076,7 +3057,7 @@ bool HOptimizedGraphBuilder::BuildGraph() {
|
| // not replayed by the Lithium translation.
|
| HEnvironment* initial_env = environment()->CopyWithoutHistory();
|
| HBasicBlock* body_entry = CreateBasicBlock(initial_env);
|
| - current_block()->Goto(body_entry);
|
| + Goto(body_entry);
|
| body_entry->SetJoinId(BailoutId::FunctionEntry());
|
| set_current_block(body_entry);
|
|
|
| @@ -3234,12 +3215,6 @@ void HGraph::RestoreActualValues() {
|
| }
|
|
|
|
|
| -void HGraphBuilder::PushAndAdd(HInstruction* instr) {
|
| - Push(instr);
|
| - AddInstruction(instr);
|
| -}
|
| -
|
| -
|
| template <class Instruction>
|
| HInstruction* HOptimizedGraphBuilder::PreProcessCall(Instruction* call) {
|
| int count = call->argument_count();
|
| @@ -3260,10 +3235,6 @@ void HOptimizedGraphBuilder::SetUpScope(Scope* scope) {
|
| HInstruction* context = Add<HContext>();
|
| environment()->BindContext(context);
|
|
|
| - HConstant* undefined_constant = HConstant::cast(Add<HConstant>(
|
| - isolate()->factory()->undefined_value()));
|
| - graph()->set_undefined_constant(undefined_constant);
|
| -
|
| // Create an arguments object containing the initial parameters. Set the
|
| // initial values of parameters including "this" having parameter index 0.
|
| ASSERT_EQ(scope->num_parameters() + 1, environment()->parameter_count());
|
| @@ -3277,6 +3248,7 @@ void HOptimizedGraphBuilder::SetUpScope(Scope* scope) {
|
| AddInstruction(arguments_object);
|
| graph()->SetArgumentsObject(arguments_object);
|
|
|
| + HConstant* undefined_constant = graph()->GetConstantUndefined();
|
| // Initialize specials and locals to undefined.
|
| for (int i = environment()->parameter_count() + 1;
|
| i < environment()->length();
|
| @@ -3319,7 +3291,7 @@ void HOptimizedGraphBuilder::VisitBlock(Block* stmt) {
|
| }
|
| HBasicBlock* break_block = break_info.break_block();
|
| if (break_block != NULL) {
|
| - if (current_block() != NULL) current_block()->Goto(break_block);
|
| + if (current_block() != NULL) Goto(break_block);
|
| break_block->SetJoinId(stmt->ExitId());
|
| set_current_block(break_block);
|
| }
|
| @@ -3429,7 +3401,7 @@ void HOptimizedGraphBuilder::VisitContinueStatement(
|
| HBasicBlock* continue_block = break_scope()->Get(
|
| stmt->target(), BreakAndContinueScope::CONTINUE, &drop_extra);
|
| Drop(drop_extra);
|
| - current_block()->Goto(continue_block);
|
| + Goto(continue_block);
|
| set_current_block(NULL);
|
| }
|
|
|
| @@ -3442,7 +3414,7 @@ void HOptimizedGraphBuilder::VisitBreakStatement(BreakStatement* stmt) {
|
| HBasicBlock* break_block = break_scope()->Get(
|
| stmt->target(), BreakAndContinueScope::BREAK, &drop_extra);
|
| Drop(drop_extra);
|
| - current_block()->Goto(break_block);
|
| + Goto(break_block);
|
| set_current_block(NULL);
|
| }
|
|
|
| @@ -3465,26 +3437,26 @@ void HOptimizedGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) {
|
| if (context->IsTest()) {
|
| TestContext* test = TestContext::cast(context);
|
| CHECK_ALIVE(VisitForEffect(stmt->expression()));
|
| - current_block()->Goto(test->if_true(), state);
|
| + Goto(test->if_true(), state);
|
| } else if (context->IsEffect()) {
|
| CHECK_ALIVE(VisitForEffect(stmt->expression()));
|
| - current_block()->Goto(function_return(), state);
|
| + Goto(function_return(), state);
|
| } else {
|
| ASSERT(context->IsValue());
|
| CHECK_ALIVE(VisitForValue(stmt->expression()));
|
| HValue* return_value = Pop();
|
| HValue* receiver = environment()->arguments_environment()->Lookup(0);
|
| HHasInstanceTypeAndBranch* typecheck =
|
| - new(zone()) HHasInstanceTypeAndBranch(return_value,
|
| - FIRST_SPEC_OBJECT_TYPE,
|
| - LAST_SPEC_OBJECT_TYPE);
|
| + New<HHasInstanceTypeAndBranch>(return_value,
|
| + FIRST_SPEC_OBJECT_TYPE,
|
| + LAST_SPEC_OBJECT_TYPE);
|
| HBasicBlock* if_spec_object = graph()->CreateBasicBlock();
|
| HBasicBlock* not_spec_object = graph()->CreateBasicBlock();
|
| typecheck->SetSuccessorAt(0, if_spec_object);
|
| typecheck->SetSuccessorAt(1, not_spec_object);
|
| - current_block()->Finish(typecheck);
|
| - if_spec_object->AddLeaveInlined(return_value, state);
|
| - not_spec_object->AddLeaveInlined(receiver, state);
|
| + FinishCurrentBlock(typecheck);
|
| + AddLeaveInlined(if_spec_object, return_value, state);
|
| + AddLeaveInlined(not_spec_object, receiver, state);
|
| }
|
| } else if (state->inlining_kind() == SETTER_CALL_RETURN) {
|
| // Return from an inlined setter call. The returned value is never used, the
|
| @@ -3494,11 +3466,11 @@ void HOptimizedGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) {
|
| HValue* rhs = environment()->arguments_environment()->Lookup(1);
|
| context->ReturnValue(rhs);
|
| } else if (context->IsEffect()) {
|
| - current_block()->Goto(function_return(), state);
|
| + Goto(function_return(), state);
|
| } else {
|
| ASSERT(context->IsValue());
|
| HValue* rhs = environment()->arguments_environment()->Lookup(1);
|
| - current_block()->AddLeaveInlined(rhs, state);
|
| + AddLeaveInlined(rhs, state);
|
| }
|
| } else {
|
| // Return from a normal inlined function. Visit the subexpression in the
|
| @@ -3508,11 +3480,11 @@ void HOptimizedGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) {
|
| VisitForControl(stmt->expression(), test->if_true(), test->if_false());
|
| } else if (context->IsEffect()) {
|
| CHECK_ALIVE(VisitForEffect(stmt->expression()));
|
| - current_block()->Goto(function_return(), state);
|
| + Goto(function_return(), state);
|
| } else {
|
| ASSERT(context->IsValue());
|
| CHECK_ALIVE(VisitForValue(stmt->expression()));
|
| - current_block()->AddLeaveInlined(Pop(), state);
|
| + AddLeaveInlined(Pop(), state);
|
| }
|
| }
|
| set_current_block(NULL);
|
| @@ -3560,7 +3532,7 @@ void HOptimizedGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
|
| not_string_block = graph()->CreateBasicBlock();
|
| string_check = New<HIsStringAndBranch>(
|
| tag_value, first_test_block, not_string_block);
|
| - current_block()->Finish(string_check);
|
| + FinishCurrentBlock(string_check);
|
|
|
| set_current_block(first_test_block);
|
| }
|
| @@ -3603,7 +3575,7 @@ void HOptimizedGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
|
|
|
| compare->SetSuccessorAt(0, body_block);
|
| compare->SetSuccessorAt(1, next_test_block);
|
| - current_block()->Finish(compare);
|
| + FinishCurrentBlock(compare);
|
|
|
| set_current_block(next_test_block);
|
| }
|
| @@ -3684,8 +3656,8 @@ void HOptimizedGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
|
| last_block,
|
| stmt->ExitId()));
|
| } else {
|
| - if (fall_through_block != NULL) fall_through_block->Goto(break_block);
|
| - if (last_block != NULL) last_block->Goto(break_block);
|
| + if (fall_through_block != NULL) Goto(fall_through_block, break_block);
|
| + if (last_block != NULL) Goto(last_block, break_block);
|
| break_block->SetJoinId(stmt->ExitId());
|
| set_current_block(break_block);
|
| }
|
| @@ -3890,7 +3862,7 @@ void HOptimizedGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
|
|
|
| compare_index->SetSuccessorAt(0, loop_body);
|
| compare_index->SetSuccessorAt(1, loop_successor);
|
| - current_block()->Finish(compare_index);
|
| + FinishCurrentBlock(compare_index);
|
|
|
| set_current_block(loop_successor);
|
| Drop(5);
|
| @@ -3920,9 +3892,7 @@ void HOptimizedGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
|
| set_current_block(body_exit);
|
|
|
| HValue* current_index = Pop();
|
| - HInstruction* new_index = New<HAdd>(current_index,
|
| - graph()->GetConstant1());
|
| - PushAndAdd(new_index);
|
| + Push(Add<HAdd>(current_index, graph()->GetConstant1()));
|
| body_exit = current_block();
|
| }
|
|
|
| @@ -3969,6 +3939,11 @@ void HOptimizedGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) {
|
| }
|
|
|
|
|
| +void HOptimizedGraphBuilder::VisitCaseClause(CaseClause* clause) {
|
| + UNREACHABLE();
|
| +}
|
| +
|
| +
|
| static Handle<SharedFunctionInfo> SearchSharedFunctionInfo(
|
| Code* unoptimized_code, FunctionLiteral* expr) {
|
| int start_position = expr->start_position();
|
| @@ -4124,19 +4099,15 @@ void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
|
| return ast_context()->ReturnInstruction(constant, expr->id());
|
| } else {
|
| HLoadGlobalCell* instr =
|
| - new(zone()) HLoadGlobalCell(cell, lookup.GetPropertyDetails());
|
| + New<HLoadGlobalCell>(cell, lookup.GetPropertyDetails());
|
| return ast_context()->ReturnInstruction(instr, expr->id());
|
| }
|
| } else {
|
| - HValue* context = environment()->context();
|
| - HGlobalObject* global_object = new(zone()) HGlobalObject(context);
|
| - AddInstruction(global_object);
|
| + HGlobalObject* global_object = Add<HGlobalObject>();
|
| HLoadGlobalGeneric* instr =
|
| - new(zone()) HLoadGlobalGeneric(context,
|
| - global_object,
|
| - variable->name(),
|
| - ast_context()->is_for_typeof());
|
| - instr->set_position(expr->position());
|
| + New<HLoadGlobalGeneric>(global_object,
|
| + variable->name(),
|
| + ast_context()->is_for_typeof());
|
| return ast_context()->ReturnInstruction(instr, expr->id());
|
| }
|
| }
|
| @@ -4254,7 +4225,11 @@ static bool LookupSetter(Handle<Map> map,
|
| Handle<AccessorPair> accessors;
|
| if (LookupAccessorPair(map, name, &accessors, holder) &&
|
| accessors->setter()->IsJSFunction()) {
|
| - *setter = Handle<JSFunction>(JSFunction::cast(accessors->setter()));
|
| + Handle<JSFunction> func(JSFunction::cast(accessors->setter()));
|
| + CallOptimization call_optimization(func);
|
| + // TODO(dcarney): temporary hack unless crankshaft can handle api calls.
|
| + if (call_optimization.is_simple_api_call()) return false;
|
| + *setter = func;
|
| return true;
|
| }
|
| return false;
|
| @@ -4335,15 +4310,23 @@ void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
|
|
|
| // Check whether to use fast or slow deep-copying for boilerplate.
|
| int max_properties = kMaxFastLiteralProperties;
|
| - Handle<Object> boilerplate(closure->literals()->get(
|
| - expr->literal_index()), isolate());
|
| - if (boilerplate->IsJSObject() &&
|
| - IsFastLiteral(Handle<JSObject>::cast(boilerplate),
|
| - kMaxFastLiteralDepth,
|
| - &max_properties)) {
|
| - Handle<JSObject> boilerplate_object = Handle<JSObject>::cast(boilerplate);
|
| + Handle<Object> literals_cell(closure->literals()->get(expr->literal_index()),
|
| + isolate());
|
| + Handle<AllocationSite> site;
|
| + Handle<JSObject> boilerplate;
|
| + if (!literals_cell->IsUndefined()) {
|
| + // Retrieve the boilerplate
|
| + site = Handle<AllocationSite>::cast(literals_cell);
|
| + boilerplate = Handle<JSObject>(JSObject::cast(site->transition_info()),
|
| + isolate());
|
| + }
|
|
|
| - literal = BuildFastLiteral(boilerplate_object);
|
| + if (!boilerplate.is_null() &&
|
| + IsFastLiteral(boilerplate, kMaxFastLiteralDepth, &max_properties)) {
|
| + AllocationSiteUsageContext usage_context(isolate(), site, false);
|
| + usage_context.EnterNewScope();
|
| + literal = BuildFastLiteral(boilerplate, &usage_context);
|
| + usage_context.ExitScope(site, boilerplate);
|
| } else {
|
| NoObservableSideEffectsScope no_effects(this);
|
| Handle<FixedArray> closure_literals(closure->literals(), isolate());
|
| @@ -4359,6 +4342,9 @@ void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
|
| Add<HPushArgument>(Add<HConstant>(constant_properties));
|
| Add<HPushArgument>(Add<HConstant>(flags));
|
|
|
| + // TODO(mvstanton): Add a flag to turn off creation of any
|
| + // AllocationMementos for this call: we are in crankshaft and should have
|
| + // learned enough about transition behavior to stop emitting mementos.
|
| Runtime::FunctionId function_id = Runtime::kCreateObjectLiteral;
|
| literal = Add<HCallRuntime>(isolate()->factory()->empty_string(),
|
| Runtime::FunctionForId(function_id),
|
| @@ -4449,45 +4435,50 @@ void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
|
| bool uninitialized = false;
|
| Handle<Object> literals_cell(literals->get(expr->literal_index()),
|
| isolate());
|
| - Handle<Object> raw_boilerplate;
|
| + Handle<JSObject> boilerplate_object;
|
| if (literals_cell->IsUndefined()) {
|
| uninitialized = true;
|
| - raw_boilerplate = Runtime::CreateArrayLiteralBoilerplate(
|
| + Handle<Object> raw_boilerplate = Runtime::CreateArrayLiteralBoilerplate(
|
| isolate(), literals, expr->constant_elements());
|
| if (raw_boilerplate.is_null()) {
|
| return Bailout(kArrayBoilerplateCreationFailed);
|
| }
|
|
|
| - site = isolate()->factory()->NewAllocationSite();
|
| - site->set_transition_info(*raw_boilerplate);
|
| + boilerplate_object = Handle<JSObject>::cast(raw_boilerplate);
|
| + AllocationSiteCreationContext creation_context(isolate());
|
| + site = creation_context.EnterNewScope();
|
| + if (JSObject::DeepWalk(boilerplate_object, &creation_context).is_null()) {
|
| + return Bailout(kArrayBoilerplateCreationFailed);
|
| + }
|
| + creation_context.ExitScope(site, boilerplate_object);
|
| literals->set(expr->literal_index(), *site);
|
|
|
| - if (JSObject::cast(*raw_boilerplate)->elements()->map() ==
|
| + if (boilerplate_object->elements()->map() ==
|
| isolate()->heap()->fixed_cow_array_map()) {
|
| isolate()->counters()->cow_arrays_created_runtime()->Increment();
|
| }
|
| } else {
|
| ASSERT(literals_cell->IsAllocationSite());
|
| site = Handle<AllocationSite>::cast(literals_cell);
|
| - raw_boilerplate = Handle<Object>(site->transition_info(), isolate());
|
| + boilerplate_object = Handle<JSObject>(
|
| + JSObject::cast(site->transition_info()), isolate());
|
| }
|
|
|
| - ASSERT(!raw_boilerplate.is_null());
|
| - ASSERT(site->IsLiteralSite());
|
| + ASSERT(!boilerplate_object.is_null());
|
| + ASSERT(site->SitePointsToLiteral());
|
|
|
| - Handle<JSObject> boilerplate_object =
|
| - Handle<JSObject>::cast(raw_boilerplate);
|
| ElementsKind boilerplate_elements_kind =
|
| - Handle<JSObject>::cast(boilerplate_object)->GetElementsKind();
|
| -
|
| - ASSERT(AllocationSite::CanTrack(boilerplate_object->map()->instance_type()));
|
| + boilerplate_object->GetElementsKind();
|
|
|
| // Check whether to use fast or slow deep-copying for boilerplate.
|
| int max_properties = kMaxFastLiteralProperties;
|
| if (IsFastLiteral(boilerplate_object,
|
| kMaxFastLiteralDepth,
|
| &max_properties)) {
|
| - literal = BuildFastLiteral(boilerplate_object);
|
| + AllocationSiteUsageContext usage_context(isolate(), site, false);
|
| + usage_context.EnterNewScope();
|
| + literal = BuildFastLiteral(boilerplate_object, &usage_context);
|
| + usage_context.ExitScope(site, boilerplate_object);
|
| } else {
|
| NoObservableSideEffectsScope no_effects(this);
|
| // Boilerplate already exists and constant elements are never accessed,
|
| @@ -4499,6 +4490,9 @@ void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
|
| Add<HPushArgument>(Add<HConstant>(literal_index));
|
| Add<HPushArgument>(Add<HConstant>(constants));
|
|
|
| + // TODO(mvstanton): Consider a flag to turn off creation of any
|
| + // AllocationMementos for this call: we are in crankshaft and should have
|
| + // learned enough about transition behavior to stop emitting mementos.
|
| Runtime::FunctionId function_id = (expr->depth() > 1)
|
| ? Runtime::kCreateArrayLiteral : Runtime::kCreateArrayLiteralShallow;
|
| literal = Add<HCallRuntime>(isolate()->factory()->empty_string(),
|
| @@ -4652,9 +4646,7 @@ HInstruction* HOptimizedGraphBuilder::BuildStoreNamedGeneric(
|
| HValue* object,
|
| Handle<String> name,
|
| HValue* value) {
|
| - HValue* context = environment()->context();
|
| - return new(zone()) HStoreNamedGeneric(
|
| - context,
|
| + return New<HStoreNamedGeneric>(
|
| object,
|
| name,
|
| value,
|
| @@ -4750,7 +4742,11 @@ bool HOptimizedGraphBuilder::PropertyAccessInfo::LoadResult(Handle<Map> map) {
|
| if (!callback->IsAccessorPair()) return false;
|
| Object* getter = Handle<AccessorPair>::cast(callback)->getter();
|
| if (!getter->IsJSFunction()) return false;
|
| - accessor_ = handle(JSFunction::cast(getter));
|
| + Handle<JSFunction> accessor = handle(JSFunction::cast(getter));
|
| + CallOptimization call_optimization(accessor);
|
| + // TODO(dcarney): temporary hack unless crankshaft can handle api calls.
|
| + if (call_optimization.is_simple_api_call()) return false;
|
| + accessor_ = accessor;
|
| } else if (lookup_.IsConstant()) {
|
| constant_ = handle(lookup_.GetConstantFromMap(*map), isolate());
|
| }
|
| @@ -4763,6 +4759,9 @@ bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupInPrototypes() {
|
| Handle<Map> map = map_;
|
| while (map->prototype()->IsJSObject()) {
|
| holder_ = handle(JSObject::cast(map->prototype()));
|
| + if (holder_->map()->is_deprecated()) {
|
| + JSObject::TryMigrateInstance(holder_);
|
| + }
|
| map = Handle<Map>(holder_->map());
|
| if (!CanInlinePropertyAccess(*map)) {
|
| lookup_.NotFound();
|
| @@ -4869,7 +4868,6 @@ HInstruction* HOptimizedGraphBuilder::BuildLoadMonomorphic(
|
|
|
|
|
| void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField(
|
| - int position,
|
| BailoutId ast_id,
|
| BailoutId return_id,
|
| HValue* object,
|
| @@ -4890,7 +4888,7 @@ void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField(
|
| HBasicBlock* if_false = graph()->CreateBasicBlock();
|
| HCompareMap* compare = New<HCompareMap>(
|
| object, info.map(), if_true, if_false);
|
| - current_block()->Finish(compare);
|
| + FinishCurrentBlock(compare);
|
|
|
| set_current_block(if_true);
|
|
|
| @@ -4900,13 +4898,12 @@ void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField(
|
| if (HasStackOverflow()) return;
|
| } else {
|
| if (!load->IsLinked()) {
|
| - load->set_position(position);
|
| AddInstruction(load);
|
| }
|
| if (!ast_context()->IsEffect()) Push(load);
|
| }
|
|
|
| - if (current_block() != NULL) current_block()->Goto(join);
|
| + if (current_block() != NULL) Goto(join);
|
| set_current_block(if_false);
|
| }
|
| }
|
| @@ -4921,14 +4918,11 @@ void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField(
|
| if (!ast_context()->IsEffect()) Push(graph()->GetConstant0());
|
| FinishExitWithHardDeoptimization("Unknown map in polymorphic load", join);
|
| } else {
|
| - HValue* context = environment()->context();
|
| - HInstruction* load = new(zone()) HLoadNamedGeneric(context, object, name);
|
| - load->set_position(position);
|
| - AddInstruction(load);
|
| + HInstruction* load = Add<HLoadNamedGeneric>(object, name);
|
| if (!ast_context()->IsEffect()) Push(load);
|
|
|
| if (join != NULL) {
|
| - current_block()->Goto(join);
|
| + Goto(join);
|
| } else {
|
| Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
|
| if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
|
| @@ -4944,7 +4938,6 @@ void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField(
|
|
|
|
|
| bool HOptimizedGraphBuilder::TryStorePolymorphicAsMonomorphic(
|
| - int position,
|
| BailoutId assignment_id,
|
| HValue* object,
|
| HValue* value,
|
| @@ -4994,7 +4987,6 @@ bool HOptimizedGraphBuilder::TryStorePolymorphicAsMonomorphic(
|
| checked_object, name, value, types->at(count - 1), &lookup),
|
| true);
|
| if (!ast_context()->IsEffect()) Push(value);
|
| - store->set_position(position);
|
| AddInstruction(store);
|
| Add<HSimulate>(assignment_id);
|
| if (!ast_context()->IsEffect()) Drop(1);
|
| @@ -5004,14 +4996,13 @@ bool HOptimizedGraphBuilder::TryStorePolymorphicAsMonomorphic(
|
|
|
|
|
| void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField(
|
| - int position,
|
| BailoutId assignment_id,
|
| HValue* object,
|
| HValue* value,
|
| SmallMapList* types,
|
| Handle<String> name) {
|
| if (TryStorePolymorphicAsMonomorphic(
|
| - position, assignment_id, object, value, types, name)) {
|
| + assignment_id, object, value, types, name)) {
|
| return;
|
| }
|
|
|
| @@ -5032,17 +5023,16 @@ void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField(
|
| HBasicBlock* if_true = graph()->CreateBasicBlock();
|
| HBasicBlock* if_false = graph()->CreateBasicBlock();
|
| HCompareMap* compare = New<HCompareMap>(object, map, if_true, if_false);
|
| - current_block()->Finish(compare);
|
| + FinishCurrentBlock(compare);
|
|
|
| set_current_block(if_true);
|
| HInstruction* instr;
|
| CHECK_ALIVE(instr = BuildStoreNamedField(
|
| compare, name, value, map, &lookup));
|
| - instr->set_position(position);
|
| // Goto will add the HSimulate for the store.
|
| AddInstruction(instr);
|
| if (!ast_context()->IsEffect()) Push(value);
|
| - current_block()->Goto(join);
|
| + Goto(join);
|
|
|
| set_current_block(if_false);
|
| }
|
| @@ -5055,14 +5045,13 @@ void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField(
|
| FinishExitWithHardDeoptimization("Unknown map in polymorphic store", join);
|
| } else {
|
| HInstruction* instr = BuildStoreNamedGeneric(object, name, value);
|
| - instr->set_position(position);
|
| AddInstruction(instr);
|
|
|
| if (join != NULL) {
|
| if (!ast_context()->IsEffect()) {
|
| Push(value);
|
| }
|
| - current_block()->Goto(join);
|
| + Goto(join);
|
| } else {
|
| // The HSimulate for the store should not see the stored value in
|
| // effect contexts (it is not materialized at expr->id() in the
|
| @@ -5116,8 +5105,7 @@ void HOptimizedGraphBuilder::BuildStore(Expression* expr,
|
| HValue* key = environment()->ExpressionStackAt(1);
|
| HValue* object = environment()->ExpressionStackAt(2);
|
| bool has_side_effects = false;
|
| - HandleKeyedElementAccess(object, key, value, expr, return_id,
|
| - expr->position(),
|
| + HandleKeyedElementAccess(object, key, value, expr,
|
| true, // is_store
|
| &has_side_effects);
|
| Drop(3);
|
| @@ -5166,15 +5154,13 @@ void HOptimizedGraphBuilder::BuildStore(Expression* expr,
|
| }
|
| } else if (types != NULL && types->length() > 1) {
|
| Drop(2);
|
| - return HandlePolymorphicStoreNamedField(
|
| - expr->position(), ast_id, object, value, types, name);
|
| + return HandlePolymorphicStoreNamedField(ast_id, object, value, types, name);
|
| } else {
|
| Drop(2);
|
| instr = BuildStoreNamedGeneric(object, name, value);
|
| }
|
|
|
| if (!ast_context()->IsEffect()) Push(value);
|
| - instr->set_position(expr->position());
|
| AddInstruction(instr);
|
| if (instr->HasObservableSideEffects()) {
|
| Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
|
| @@ -5203,7 +5189,6 @@ void HOptimizedGraphBuilder::HandlePropertyAssignment(Assignment* expr) {
|
| void HOptimizedGraphBuilder::HandleGlobalVariableAssignment(
|
| Variable* var,
|
| HValue* value,
|
| - int position,
|
| BailoutId ast_id) {
|
| LookupResult lookup(isolate());
|
| GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true);
|
| @@ -5226,7 +5211,6 @@ void HOptimizedGraphBuilder::HandleGlobalVariableAssignment(
|
| }
|
| HInstruction* instr =
|
| Add<HStoreGlobalCell>(value, cell, lookup.GetPropertyDetails());
|
| - instr->set_position(position);
|
| if (instr->HasObservableSideEffects()) {
|
| Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
|
| }
|
| @@ -5235,7 +5219,7 @@ void HOptimizedGraphBuilder::HandleGlobalVariableAssignment(
|
| HStoreGlobalGeneric* instr =
|
| Add<HStoreGlobalGeneric>(global_object, var->name(),
|
| value, function_strict_mode_flag());
|
| - instr->set_position(position);
|
| + USE(instr);
|
| ASSERT(instr->HasObservableSideEffects());
|
| Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
|
| }
|
| @@ -5264,7 +5248,6 @@ void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
|
| case Variable::UNALLOCATED:
|
| HandleGlobalVariableAssignment(var,
|
| Top(),
|
| - expr->position(),
|
| expr->AssignmentId());
|
| break;
|
|
|
| @@ -5332,14 +5315,15 @@ void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
|
| key = Top();
|
| }
|
|
|
| - CHECK_ALIVE(PushLoad(prop, object, key, expr->position()));
|
| + CHECK_ALIVE(PushLoad(prop, object, key));
|
|
|
| CHECK_ALIVE(VisitForValue(expr->value()));
|
| HValue* right = Pop();
|
| HValue* left = Pop();
|
|
|
| HInstruction* instr = BuildBinaryOperation(operation, left, right);
|
| - PushAndAdd(instr);
|
| + AddInstruction(instr);
|
| + Push(instr);
|
| if (instr->HasObservableSideEffects()) {
|
| Add<HSimulate>(operation->id(), REMOVABLE_SIMULATE);
|
| }
|
| @@ -5395,7 +5379,6 @@ void HOptimizedGraphBuilder::VisitAssignment(Assignment* expr) {
|
| CHECK_ALIVE(VisitForValue(expr->value()));
|
| HandleGlobalVariableAssignment(var,
|
| Top(),
|
| - expr->position(),
|
| expr->AssignmentId());
|
| return ast_context()->ReturnValue(Pop());
|
|
|
| @@ -5494,16 +5477,15 @@ void HOptimizedGraphBuilder::VisitThrow(Throw* expr) {
|
| CHECK_ALIVE(VisitForValue(expr->exception()));
|
|
|
| HValue* value = environment()->Pop();
|
| - HThrow* instr = Add<HThrow>(value);
|
| - instr->set_position(expr->position());
|
| + if (!FLAG_emit_opt_code_positions) SetSourcePosition(expr->position());
|
| + Add<HThrow>(value);
|
| Add<HSimulate>(expr->id());
|
|
|
| // If the throw definitely exits the function, we can finish with a dummy
|
| // control flow at this point. This is not the case if the throw is inside
|
| // an inlined function which may be replaced.
|
| if (call_context() == NULL) {
|
| - current_block()->FinishExit(new(zone()) HAbnormalExit);
|
| - set_current_block(NULL);
|
| + FinishExitCurrentBlock(New<HAbnormalExit>());
|
| }
|
| }
|
|
|
| @@ -5523,6 +5505,12 @@ HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object,
|
| }
|
|
|
|
|
| +HInstruction* HGraphBuilder::AddLoadNamedField(HValue* object,
|
| + HObjectAccess access) {
|
| + return AddInstruction(BuildLoadNamedField(object, access));
|
| +}
|
| +
|
| +
|
| HInstruction* HGraphBuilder::BuildLoadStringLength(HValue* object,
|
| HValue* checked_string) {
|
| if (FLAG_fold_constants && object->IsConstant()) {
|
| @@ -5543,16 +5531,14 @@ HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric(
|
| Add<HDeoptimize>("Insufficient type feedback for generic named load",
|
| Deoptimizer::SOFT);
|
| }
|
| - HValue* context = environment()->context();
|
| - return new(zone()) HLoadNamedGeneric(context, object, name);
|
| + return New<HLoadNamedGeneric>(object, name);
|
| }
|
|
|
|
|
|
|
| HInstruction* HOptimizedGraphBuilder::BuildLoadKeyedGeneric(HValue* object,
|
| HValue* key) {
|
| - HValue* context = environment()->context();
|
| - return new(zone()) HLoadKeyedGeneric(context, object, key);
|
| + return New<HLoadKeyedGeneric>(object, key);
|
| }
|
|
|
|
|
| @@ -5666,8 +5652,6 @@ HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess(
|
| HValue* key,
|
| HValue* val,
|
| SmallMapList* maps,
|
| - BailoutId ast_id,
|
| - int position,
|
| bool is_store,
|
| KeyedAccessStoreMode store_mode,
|
| bool* has_side_effects) {
|
| @@ -5679,9 +5663,6 @@ HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess(
|
| TryBuildConsolidatedElementLoad(object, key, val, maps);
|
| if (consolidated_load != NULL) {
|
| *has_side_effects |= consolidated_load->HasObservableSideEffects();
|
| - if (position != RelocInfo::kNoPosition) {
|
| - consolidated_load->set_position(position);
|
| - }
|
| return consolidated_load;
|
| }
|
| }
|
| @@ -5738,7 +5719,6 @@ HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess(
|
| store_mode);
|
| }
|
| *has_side_effects |= instr->HasObservableSideEffects();
|
| - if (position != RelocInfo::kNoPosition) instr->set_position(position);
|
| return is_store ? NULL : instr;
|
| }
|
|
|
| @@ -5752,7 +5732,7 @@ HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess(
|
| HBasicBlock* other_map = graph()->CreateBasicBlock();
|
| HCompareMap* mapcompare =
|
| New<HCompareMap>(object, map, this_map, other_map);
|
| - current_block()->Finish(mapcompare);
|
| + FinishCurrentBlock(mapcompare);
|
|
|
| set_current_block(this_map);
|
| HInstruction* access = NULL;
|
| @@ -5775,12 +5755,11 @@ HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess(
|
| *has_side_effects |= access->HasObservableSideEffects();
|
| // The caller will use has_side_effects and add a correct Simulate.
|
| access->SetFlag(HValue::kHasNoObservableSideEffects);
|
| - if (position != RelocInfo::kNoPosition) access->set_position(position);
|
| if (!is_store) {
|
| Push(access);
|
| }
|
| NoObservableSideEffectsScope scope(this);
|
| - current_block()->GotoNoSimulate(join);
|
| + GotoNoSimulate(join);
|
| set_current_block(other_map);
|
| }
|
|
|
| @@ -5798,8 +5777,6 @@ HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess(
|
| HValue* key,
|
| HValue* val,
|
| Expression* expr,
|
| - BailoutId ast_id,
|
| - int position,
|
| bool is_store,
|
| bool* has_side_effects) {
|
| ASSERT(!expr->IsPropertyName());
|
| @@ -5821,17 +5798,18 @@ HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess(
|
| }
|
| } else if (types != NULL && !types->is_empty()) {
|
| return HandlePolymorphicElementAccess(
|
| - obj, key, val, types, ast_id, position, is_store,
|
| + obj, key, val, types, is_store,
|
| expr->GetStoreMode(), has_side_effects);
|
| } else {
|
| if (is_store) {
|
| - if (expr->IsAssignment() && expr->AsAssignment()->IsUninitialized()) {
|
| + if (expr->IsAssignment() &&
|
| + expr->AsAssignment()->HasNoTypeInformation()) {
|
| Add<HDeoptimize>("Insufficient type feedback for keyed store",
|
| Deoptimizer::SOFT);
|
| }
|
| instr = BuildStoreKeyedGeneric(obj, key, val);
|
| } else {
|
| - if (expr->AsProperty()->IsUninitialized()) {
|
| + if (expr->AsProperty()->HasNoTypeInformation()) {
|
| Add<HDeoptimize>("Insufficient type feedback for keyed load",
|
| Deoptimizer::SOFT);
|
| }
|
| @@ -5839,7 +5817,6 @@ HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess(
|
| }
|
| AddInstruction(instr);
|
| }
|
| - if (position != RelocInfo::kNoPosition) instr->set_position(position);
|
| *has_side_effects = instr->HasObservableSideEffects();
|
| return instr;
|
| }
|
| @@ -5849,9 +5826,7 @@ HInstruction* HOptimizedGraphBuilder::BuildStoreKeyedGeneric(
|
| HValue* object,
|
| HValue* key,
|
| HValue* value) {
|
| - HValue* context = environment()->context();
|
| - return new(zone()) HStoreKeyedGeneric(
|
| - context,
|
| + return New<HStoreKeyedGeneric>(
|
| object,
|
| key,
|
| value,
|
| @@ -5918,7 +5893,7 @@ bool HOptimizedGraphBuilder::TryArgumentsAccess(Property* expr) {
|
| HInstruction* elements = Add<HArgumentsElements>(false);
|
| HInstruction* length = Add<HArgumentsLength>(elements);
|
| HInstruction* checked_key = Add<HBoundsCheck>(key, length);
|
| - result = new(zone()) HAccessArgumentsAt(elements, length, checked_key);
|
| + result = New<HAccessArgumentsAt>(elements, length, checked_key);
|
| } else {
|
| EnsureArgumentsArePushedForAccess();
|
|
|
| @@ -5928,7 +5903,7 @@ bool HOptimizedGraphBuilder::TryArgumentsAccess(Property* expr) {
|
| arguments_environment()->parameter_count() - 1;
|
| HInstruction* length = Add<HConstant>(argument_count);
|
| HInstruction* checked_key = Add<HBoundsCheck>(key, length);
|
| - result = new(zone()) HAccessArgumentsAt(elements, length, checked_key);
|
| + result = New<HAccessArgumentsAt>(elements, length, checked_key);
|
| }
|
| }
|
| ast_context()->ReturnInstruction(result, expr->id());
|
| @@ -5938,12 +5913,11 @@ bool HOptimizedGraphBuilder::TryArgumentsAccess(Property* expr) {
|
|
|
| void HOptimizedGraphBuilder::PushLoad(Property* expr,
|
| HValue* object,
|
| - HValue* key,
|
| - int position) {
|
| + HValue* key) {
|
| ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED);
|
| Push(object);
|
| if (key != NULL) Push(key);
|
| - BuildLoad(expr, position, expr->LoadId());
|
| + BuildLoad(expr, expr->LoadId());
|
| }
|
|
|
|
|
| @@ -5956,22 +5930,19 @@ static bool AreStringTypes(SmallMapList* types) {
|
|
|
|
|
| void HOptimizedGraphBuilder::BuildLoad(Property* expr,
|
| - int position,
|
| BailoutId ast_id) {
|
| HInstruction* instr = NULL;
|
| if (expr->IsStringAccess()) {
|
| HValue* index = Pop();
|
| HValue* string = Pop();
|
| - HValue* context = environment()->context();
|
| - HInstruction* char_code =
|
| - BuildStringCharCodeAt(string, index);
|
| + HInstruction* char_code = BuildStringCharCodeAt(string, index);
|
| AddInstruction(char_code);
|
| - instr = HStringCharFromCode::New(zone(), context, char_code);
|
| + instr = NewUncasted<HStringCharFromCode>(char_code);
|
|
|
| } else if (expr->IsFunctionPrototype()) {
|
| HValue* function = Pop();
|
| BuildCheckHeapObject(function);
|
| - instr = new(zone()) HLoadFunctionPrototype(function);
|
| + instr = New<HLoadFunctionPrototype>(function);
|
|
|
| } else if (expr->key()->IsPropertyName()) {
|
| Handle<String> name = expr->key()->AsLiteral()->AsPropertyName();
|
| @@ -5985,14 +5956,14 @@ void HOptimizedGraphBuilder::BuildLoad(Property* expr,
|
| PropertyAccessInfo info(isolate(), types->first(), name);
|
| if (!info.CanLoadAsMonomorphic(types)) {
|
| return HandlePolymorphicLoadNamedField(
|
| - position, ast_id, expr->LoadId(), object, types, name);
|
| + ast_id, expr->LoadId(), object, types, name);
|
| }
|
|
|
| BuildCheckHeapObject(object);
|
| HInstruction* checked_object;
|
| if (AreStringTypes(types)) {
|
| checked_object =
|
| - AddInstruction(HCheckInstanceType::NewIsString(object, zone()));
|
| + Add<HCheckInstanceType>(object, HCheckInstanceType::IS_STRING);
|
| } else {
|
| checked_object = Add<HCheckMaps>(object, types);
|
| }
|
| @@ -6010,7 +5981,7 @@ void HOptimizedGraphBuilder::BuildLoad(Property* expr,
|
|
|
| bool has_side_effects = false;
|
| HValue* load = HandleKeyedElementAccess(
|
| - obj, key, NULL, expr, ast_id, position,
|
| + obj, key, NULL, expr,
|
| false, // is_store
|
| &has_side_effects);
|
| if (has_side_effects) {
|
| @@ -6024,7 +5995,6 @@ void HOptimizedGraphBuilder::BuildLoad(Property* expr,
|
| }
|
| return ast_context()->ReturnValue(load);
|
| }
|
| - instr->set_position(position);
|
| return ast_context()->ReturnInstruction(instr, ast_id);
|
| }
|
|
|
| @@ -6042,7 +6012,7 @@ void HOptimizedGraphBuilder::VisitProperty(Property* expr) {
|
| CHECK_ALIVE(VisitForValue(expr->key()));
|
| }
|
|
|
| - BuildLoad(expr, expr->position(), expr->id());
|
| + BuildLoad(expr, expr->id());
|
| }
|
|
|
|
|
| @@ -6155,7 +6125,6 @@ bool HOptimizedGraphBuilder::TryCallPolymorphicAsMonomorphic(
|
| int argument_count = expr->arguments()->length() + 1; // Includes receiver.
|
| HCallConstantFunction* call =
|
| New<HCallConstantFunction>(expr->target(), argument_count);
|
| - call->set_position(expr->position());
|
| PreProcessCall(call);
|
| AddInstruction(call);
|
| if (!ast_context()->IsEffect()) Push(call);
|
| @@ -6219,9 +6188,9 @@ void HOptimizedGraphBuilder::HandlePolymorphicCallNamed(
|
| HBasicBlock* empty_smi_block = graph()->CreateBasicBlock();
|
| HBasicBlock* not_smi_block = graph()->CreateBasicBlock();
|
| number_block = graph()->CreateBasicBlock();
|
| - current_block()->Finish(New<HIsSmiAndBranch>(
|
| + FinishCurrentBlock(New<HIsSmiAndBranch>(
|
| receiver, empty_smi_block, not_smi_block));
|
| - empty_smi_block->Goto(number_block);
|
| + Goto(empty_smi_block, number_block);
|
| set_current_block(not_smi_block);
|
| } else {
|
| BuildCheckHeapObject(receiver);
|
| @@ -6246,10 +6215,10 @@ void HOptimizedGraphBuilder::HandlePolymorphicCallNamed(
|
| expr->set_map_check();
|
| }
|
|
|
| - current_block()->Finish(compare);
|
| + FinishCurrentBlock(compare);
|
|
|
| if (expr->check_type() == NUMBER_CHECK) {
|
| - if_true->Goto(number_block);
|
| + Goto(if_true, number_block);
|
| if_true = number_block;
|
| number_block->SetJoinId(expr->id());
|
| }
|
| @@ -6272,13 +6241,12 @@ void HOptimizedGraphBuilder::HandlePolymorphicCallNamed(
|
| } else {
|
| HCallConstantFunction* call =
|
| New<HCallConstantFunction>(expr->target(), argument_count);
|
| - call->set_position(expr->position());
|
| PreProcessCall(call);
|
| AddInstruction(call);
|
| if (!ast_context()->IsEffect()) Push(call);
|
| }
|
|
|
| - if (current_block() != NULL) current_block()->Goto(join);
|
| + if (current_block() != NULL) Goto(join);
|
| set_current_block(if_false);
|
| }
|
|
|
| @@ -6294,13 +6262,12 @@ void HOptimizedGraphBuilder::HandlePolymorphicCallNamed(
|
| FinishExitWithHardDeoptimization("Unknown map in polymorphic call", join);
|
| } else {
|
| HCallNamed* call = New<HCallNamed>(name, argument_count);
|
| - call->set_position(expr->position());
|
| PreProcessCall(call);
|
|
|
| if (join != NULL) {
|
| AddInstruction(call);
|
| if (!ast_context()->IsEffect()) Push(call);
|
| - current_block()->Goto(join);
|
| + Goto(join);
|
| } else {
|
| return ast_context()->ReturnInstruction(call, expr->id());
|
| }
|
| @@ -6602,12 +6569,12 @@ bool HOptimizedGraphBuilder::TryInline(CallKind call_kind,
|
| // return value will always evaluate to true, in a value context the
|
| // return value is the newly allocated receiver.
|
| if (call_context()->IsTest()) {
|
| - current_block()->Goto(inlined_test_context()->if_true(), state);
|
| + Goto(inlined_test_context()->if_true(), state);
|
| } else if (call_context()->IsEffect()) {
|
| - current_block()->Goto(function_return(), state);
|
| + Goto(function_return(), state);
|
| } else {
|
| ASSERT(call_context()->IsValue());
|
| - current_block()->AddLeaveInlined(implicit_return_value, state);
|
| + AddLeaveInlined(implicit_return_value, state);
|
| }
|
| } else if (state->inlining_kind() == SETTER_CALL_RETURN) {
|
| // Falling off the end of an inlined setter call. The returned value is
|
| @@ -6616,21 +6583,21 @@ bool HOptimizedGraphBuilder::TryInline(CallKind call_kind,
|
| if (call_context()->IsTest()) {
|
| inlined_test_context()->ReturnValue(implicit_return_value);
|
| } else if (call_context()->IsEffect()) {
|
| - current_block()->Goto(function_return(), state);
|
| + Goto(function_return(), state);
|
| } else {
|
| ASSERT(call_context()->IsValue());
|
| - current_block()->AddLeaveInlined(implicit_return_value, state);
|
| + AddLeaveInlined(implicit_return_value, state);
|
| }
|
| } else {
|
| // Falling off the end of a normal inlined function. This basically means
|
| // returning undefined.
|
| if (call_context()->IsTest()) {
|
| - current_block()->Goto(inlined_test_context()->if_false(), state);
|
| + Goto(inlined_test_context()->if_false(), state);
|
| } else if (call_context()->IsEffect()) {
|
| - current_block()->Goto(function_return(), state);
|
| + Goto(function_return(), state);
|
| } else {
|
| ASSERT(call_context()->IsValue());
|
| - current_block()->AddLeaveInlined(undefined, state);
|
| + AddLeaveInlined(undefined, state);
|
| }
|
| }
|
| }
|
| @@ -6652,13 +6619,13 @@ bool HOptimizedGraphBuilder::TryInline(CallKind call_kind,
|
| entry->RegisterReturnTarget(if_true, zone());
|
| if_true->SetJoinId(ast_id);
|
| HBasicBlock* true_target = TestContext::cast(ast_context())->if_true();
|
| - if_true->Goto(true_target, function_state());
|
| + Goto(if_true, true_target, function_state());
|
| }
|
| if (if_false->HasPredecessor()) {
|
| entry->RegisterReturnTarget(if_false, zone());
|
| if_false->SetJoinId(ast_id);
|
| HBasicBlock* false_target = TestContext::cast(ast_context())->if_false();
|
| - if_false->Goto(false_target, function_state());
|
| + Goto(if_false, false_target, function_state());
|
| }
|
| set_current_block(NULL);
|
| return true;
|
| @@ -6761,11 +6728,8 @@ bool HOptimizedGraphBuilder::TryInlineBuiltinFunctionCall(Call* expr,
|
| case kMathTan:
|
| if (expr->arguments()->length() == 1) {
|
| HValue* argument = Pop();
|
| - HValue* context = environment()->context();
|
| Drop(1); // Receiver.
|
| - HInstruction* op =
|
| - HUnaryMathOperation::New(zone(), context, argument, id);
|
| - op->set_position(expr->position());
|
| + HInstruction* op = NewUncasted<HUnaryMathOperation>(argument, id);
|
| if (drop_extra) Drop(1); // Optionally drop the function.
|
| ast_context()->ReturnInstruction(op, expr->id());
|
| return true;
|
| @@ -6776,8 +6740,7 @@ bool HOptimizedGraphBuilder::TryInlineBuiltinFunctionCall(Call* expr,
|
| HValue* right = Pop();
|
| HValue* left = Pop();
|
| Drop(1); // Receiver.
|
| - HValue* context = environment()->context();
|
| - HInstruction* op = HMul::NewImul(zone(), context, left, right);
|
| + HInstruction* op = HMul::NewImul(zone(), context(), left, right);
|
| if (drop_extra) Drop(1); // Optionally drop the function.
|
| ast_context()->ReturnInstruction(op, expr->id());
|
| return true;
|
| @@ -6807,7 +6770,6 @@ bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall(
|
| if (argument_count == 2 && check_type == STRING_CHECK) {
|
| HValue* index = Pop();
|
| HValue* string = Pop();
|
| - HValue* context = environment()->context();
|
| ASSERT(!expr->holder().is_null());
|
| BuildCheckPrototypeMaps(Call::GetPrototypeForPrimitiveCheck(
|
| STRING_CHECK, expr->holder()->GetIsolate()),
|
| @@ -6819,8 +6781,7 @@ bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall(
|
| return true;
|
| }
|
| AddInstruction(char_code);
|
| - HInstruction* result =
|
| - HStringCharFromCode::New(zone(), context, char_code);
|
| + HInstruction* result = NewUncasted<HStringCharFromCode>(char_code);
|
| ast_context()->ReturnInstruction(result, expr->id());
|
| return true;
|
| }
|
| @@ -6829,10 +6790,8 @@ bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall(
|
| if (argument_count == 2 && check_type == RECEIVER_MAP_CHECK) {
|
| AddCheckConstantFunction(expr->holder(), receiver, receiver_map);
|
| HValue* argument = Pop();
|
| - HValue* context = environment()->context();
|
| Drop(1); // Receiver.
|
| - HInstruction* result =
|
| - HStringCharFromCode::New(zone(), context, argument);
|
| + HInstruction* result = NewUncasted<HStringCharFromCode>(argument);
|
| ast_context()->ReturnInstruction(result, expr->id());
|
| return true;
|
| }
|
| @@ -6851,11 +6810,8 @@ bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall(
|
| if (argument_count == 2 && check_type == RECEIVER_MAP_CHECK) {
|
| AddCheckConstantFunction(expr->holder(), receiver, receiver_map);
|
| HValue* argument = Pop();
|
| - HValue* context = environment()->context();
|
| Drop(1); // Receiver.
|
| - HInstruction* op =
|
| - HUnaryMathOperation::New(zone(), context, argument, id);
|
| - op->set_position(expr->position());
|
| + HInstruction* op = NewUncasted<HUnaryMathOperation>(argument, id);
|
| ast_context()->ReturnInstruction(op, expr->id());
|
| return true;
|
| }
|
| @@ -6866,30 +6822,27 @@ bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall(
|
| HValue* right = Pop();
|
| HValue* left = Pop();
|
| Pop(); // Pop receiver.
|
| - HValue* context = environment()->context();
|
| HInstruction* result = NULL;
|
| // Use sqrt() if exponent is 0.5 or -0.5.
|
| if (right->IsConstant() && HConstant::cast(right)->HasDoubleValue()) {
|
| double exponent = HConstant::cast(right)->DoubleValue();
|
| if (exponent == 0.5) {
|
| - result =
|
| - HUnaryMathOperation::New(zone(), context, left, kMathPowHalf);
|
| + result = NewUncasted<HUnaryMathOperation>(left, kMathPowHalf);
|
| } else if (exponent == -0.5) {
|
| HValue* one = graph()->GetConstant1();
|
| - HInstruction* sqrt =
|
| - HUnaryMathOperation::New(zone(), context, left, kMathPowHalf);
|
| - AddInstruction(sqrt);
|
| + HInstruction* sqrt = AddUncasted<HUnaryMathOperation>(
|
| + left, kMathPowHalf);
|
| // MathPowHalf doesn't have side effects so there's no need for
|
| // an environment simulation here.
|
| ASSERT(!sqrt->HasObservableSideEffects());
|
| - result = HDiv::New(zone(), context, one, sqrt);
|
| + result = NewUncasted<HDiv>(one, sqrt);
|
| } else if (exponent == 2.0) {
|
| - result = HMul::New(zone(), context, left, left);
|
| + result = NewUncasted<HMul>(left, left);
|
| }
|
| }
|
|
|
| if (result == NULL) {
|
| - result = HPower::New(zone(), context, left, right);
|
| + result = NewUncasted<HPower>(left, right);
|
| }
|
| ast_context()->ReturnInstruction(result, expr->id());
|
| return true;
|
| @@ -6900,7 +6853,7 @@ bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall(
|
| AddCheckConstantFunction(expr->holder(), receiver, receiver_map);
|
| Drop(1); // Receiver.
|
| HGlobalObject* global_object = Add<HGlobalObject>();
|
| - HRandom* result = new(zone()) HRandom(global_object);
|
| + HRandom* result = New<HRandom>(global_object);
|
| ast_context()->ReturnInstruction(result, expr->id());
|
| return true;
|
| }
|
| @@ -6912,11 +6865,9 @@ bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall(
|
| HValue* right = Pop();
|
| HValue* left = Pop();
|
| Drop(1); // Receiver.
|
| - HValue* context = environment()->context();
|
| HMathMinMax::Operation op = (id == kMathMin) ? HMathMinMax::kMathMin
|
| : HMathMinMax::kMathMax;
|
| - HInstruction* result =
|
| - HMathMinMax::New(zone(), context, left, right, op);
|
| + HInstruction* result = NewUncasted<HMathMinMax>(left, right, op);
|
| ast_context()->ReturnInstruction(result, expr->id());
|
| return true;
|
| }
|
| @@ -6927,8 +6878,7 @@ bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall(
|
| HValue* right = Pop();
|
| HValue* left = Pop();
|
| Drop(1); // Receiver.
|
| - HValue* context = environment()->context();
|
| - HInstruction* result = HMul::NewImul(zone(), context, left, right);
|
| + HInstruction* result = HMul::NewImul(zone(), context(), left, right);
|
| ast_context()->ReturnInstruction(result, expr->id());
|
| return true;
|
| }
|
| @@ -6979,12 +6929,10 @@ bool HOptimizedGraphBuilder::TryCallApply(Call* expr) {
|
| HInstruction* elements = Add<HArgumentsElements>(false);
|
| HInstruction* length = Add<HArgumentsLength>(elements);
|
| HValue* wrapped_receiver = BuildWrapReceiver(receiver, function);
|
| - HInstruction* result =
|
| - new(zone()) HApplyArguments(function,
|
| - wrapped_receiver,
|
| - length,
|
| - elements);
|
| - result->set_position(expr->position());
|
| + HInstruction* result = New<HApplyArguments>(function,
|
| + wrapped_receiver,
|
| + length,
|
| + elements);
|
| ast_context()->ReturnInstruction(result, expr->id());
|
| return true;
|
| } else {
|
| @@ -7010,19 +6958,15 @@ bool HOptimizedGraphBuilder::TryCallApply(Call* expr) {
|
| }
|
|
|
| Drop(arguments_count - 1);
|
| - PushAndAdd(New<HPushArgument>(Pop()));
|
| + Push(Add<HPushArgument>(Pop()));
|
| for (int i = 1; i < arguments_count; i++) {
|
| - PushAndAdd(New<HPushArgument>(arguments_values->at(i)));
|
| + Push(Add<HPushArgument>(arguments_values->at(i)));
|
| }
|
|
|
| - HValue* context = environment()->context();
|
| - HInvokeFunction* call = new(zone()) HInvokeFunction(
|
| - context,
|
| - function,
|
| - known_function,
|
| - arguments_count);
|
| + HInvokeFunction* call = New<HInvokeFunction>(function,
|
| + known_function,
|
| + arguments_count);
|
| Drop(arguments_count);
|
| - call->set_position(expr->position());
|
| ast_context()->ReturnInstruction(call, expr->id());
|
| return true;
|
| }
|
| @@ -7053,7 +6997,6 @@ void HOptimizedGraphBuilder::VisitCall(Call* expr) {
|
| CHECK_ALIVE(VisitArgumentList(expr->arguments()));
|
|
|
| call = New<HCallKeyed>(key, argument_count);
|
| - call->set_position(expr->position());
|
| Drop(argument_count + 1); // 1 is the key.
|
| return ast_context()->ReturnInstruction(call, expr->id());
|
| }
|
| @@ -7107,7 +7050,6 @@ void HOptimizedGraphBuilder::VisitCall(Call* expr) {
|
| } else {
|
| call = PreProcessCall(New<HCallNamed>(name, argument_count));
|
| }
|
| -
|
| } else {
|
| VariableProxy* proxy = expr->expression()->AsVariableProxy();
|
| if (proxy != NULL && proxy->var()->is_possibly_eval(isolate())) {
|
| @@ -7131,9 +7073,8 @@ void HOptimizedGraphBuilder::VisitCall(Call* expr) {
|
| if (known_global_function) {
|
| // Push the global object instead of the global receiver because
|
| // code generated by the full code generator expects it.
|
| - HValue* context = environment()->context();
|
| - HGlobalObject* global_object = new(zone()) HGlobalObject(context);
|
| - PushAndAdd(global_object);
|
| + HGlobalObject* global_object = Add<HGlobalObject>();
|
| + Push(global_object);
|
| CHECK_ALIVE(VisitExpressions(expr->arguments()));
|
|
|
| CHECK_ALIVE(VisitForValue(expr->expression()));
|
| @@ -7167,12 +7108,12 @@ void HOptimizedGraphBuilder::VisitCall(Call* expr) {
|
| // because it is likely to generate better code.
|
| call = PreProcessCall(New<HCallNamed>(var->name(), argument_count));
|
| } else {
|
| - call = PreProcessCall(new(zone()) HCallKnownGlobal(expr->target(),
|
| - argument_count));
|
| + call = PreProcessCall(New<HCallKnownGlobal>(
|
| + expr->target(), argument_count));
|
| }
|
| } else {
|
| HGlobalObject* receiver = Add<HGlobalObject>();
|
| - PushAndAdd(New<HPushArgument>(receiver));
|
| + Push(Add<HPushArgument>(receiver));
|
| CHECK_ALIVE(VisitArgumentList(expr->arguments()));
|
|
|
| call = New<HCallGlobal>(var->name(), argument_count);
|
| @@ -7185,8 +7126,8 @@ void HOptimizedGraphBuilder::VisitCall(Call* expr) {
|
| CHECK_ALIVE(VisitForValue(expr->expression()));
|
| HValue* function = Top();
|
| HGlobalObject* global = Add<HGlobalObject>();
|
| - HGlobalReceiver* receiver = New<HGlobalReceiver>(global);
|
| - PushAndAdd(receiver);
|
| + HGlobalReceiver* receiver = Add<HGlobalReceiver>(global);
|
| + Push(receiver);
|
| CHECK_ALIVE(VisitExpressions(expr->arguments()));
|
| Add<HCheckValue>(function, expr->target());
|
|
|
| @@ -7212,7 +7153,7 @@ void HOptimizedGraphBuilder::VisitCall(Call* expr) {
|
| HValue* function = Top();
|
| HGlobalObject* global_object = Add<HGlobalObject>();
|
| HGlobalReceiver* receiver = Add<HGlobalReceiver>(global_object);
|
| - PushAndAdd(New<HPushArgument>(receiver));
|
| + Push(Add<HPushArgument>(receiver));
|
| CHECK_ALIVE(VisitArgumentList(expr->arguments()));
|
|
|
| call = New<HCallFunction>(function, argument_count);
|
| @@ -7220,7 +7161,6 @@ void HOptimizedGraphBuilder::VisitCall(Call* expr) {
|
| }
|
| }
|
|
|
| - call->set_position(expr->position());
|
| return ast_context()->ReturnInstruction(call, expr->id());
|
| }
|
|
|
| @@ -7238,6 +7178,7 @@ void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) {
|
| ASSERT(!HasStackOverflow());
|
| ASSERT(current_block() != NULL);
|
| ASSERT(current_block()->HasPredecessor());
|
| + if (!FLAG_emit_opt_code_positions) SetSourcePosition(expr->position());
|
| int argument_count = expr->arguments()->length() + 1; // Plus constructor.
|
| Factory* factory = isolate()->factory();
|
|
|
| @@ -7329,7 +7270,6 @@ void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) {
|
| environment()->SetExpressionStackAt(receiver_index, function);
|
| HInstruction* call =
|
| PreProcessCall(New<HCallNew>(function, argument_count));
|
| - call->set_position(expr->position());
|
| return ast_context()->ReturnInstruction(call, expr->id());
|
| } else {
|
| // The constructor function is both an operand to the instruction and an
|
| @@ -7349,7 +7289,6 @@ void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) {
|
| call = New<HCallNew>(constructor, argument_count);
|
| }
|
| Drop(argument_count);
|
| - call->set_position(expr->position());
|
| return ast_context()->ReturnInstruction(call, expr->id());
|
| }
|
| }
|
| @@ -7580,6 +7519,7 @@ void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) {
|
| ASSERT(!HasStackOverflow());
|
| ASSERT(current_block() != NULL);
|
| ASSERT(current_block()->HasPredecessor());
|
| + if (!FLAG_emit_opt_code_positions) SetSourcePosition(expr->position());
|
| Expression* target = expr->expression();
|
| VariableProxy* proxy = target->AsVariableProxy();
|
| Property* prop = target->AsProperty();
|
| @@ -7612,7 +7552,6 @@ void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) {
|
| case Variable::UNALLOCATED:
|
| HandleGlobalVariableAssignment(var,
|
| after,
|
| - expr->position(),
|
| expr->AssignmentId());
|
| break;
|
|
|
| @@ -7670,7 +7609,7 @@ void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) {
|
| key = Top();
|
| }
|
|
|
| - CHECK_ALIVE(PushLoad(prop, object, key, expr->position()));
|
| + CHECK_ALIVE(PushLoad(prop, object, key));
|
|
|
| after = BuildIncrement(returns_original_input, expr);
|
|
|
| @@ -7706,7 +7645,7 @@ HInstruction* HOptimizedGraphBuilder::BuildStringCharCodeAt(
|
| }
|
| BuildCheckHeapObject(string);
|
| HValue* checkstring =
|
| - AddInstruction(HCheckInstanceType::NewIsString(string, zone()));
|
| + Add<HCheckInstanceType>(string, HCheckInstanceType::IS_STRING);
|
| HInstruction* length = BuildLoadStringLength(string, checkstring);
|
| AddInstruction(length);
|
| HInstruction* checked_index = Add<HBoundsCheck>(index, length);
|
| @@ -7883,6 +7822,42 @@ HInstruction* HGraphBuilder::BuildBinaryOperation(
|
| right_rep = Representation::FromType(right_type);
|
| }
|
|
|
| + // Special case for string addition here.
|
| + if (op == Token::ADD &&
|
| + (left_type->Is(Type::String()) || right_type->Is(Type::String()))) {
|
| + if (left_type->Is(Type::String())) {
|
| + IfBuilder if_isstring(this);
|
| + if_isstring.If<HIsStringAndBranch>(left);
|
| + if_isstring.Then();
|
| + if_isstring.ElseDeopt("Expected string for LHS of binary operation");
|
| + } else if (left_type->Is(Type::Number())) {
|
| + left = BuildNumberToString(left, left_type);
|
| + } else {
|
| + ASSERT(right_type->Is(Type::String()));
|
| + HValue* function = AddLoadJSBuiltin(Builtins::STRING_ADD_RIGHT);
|
| + Add<HPushArgument>(left);
|
| + Add<HPushArgument>(right);
|
| + return NewUncasted<HInvokeFunction>(function, 2);
|
| + }
|
| +
|
| + if (right_type->Is(Type::String())) {
|
| + IfBuilder if_isstring(this);
|
| + if_isstring.If<HIsStringAndBranch>(right);
|
| + if_isstring.Then();
|
| + if_isstring.ElseDeopt("Expected string for RHS of binary operation");
|
| + } else if (right_type->Is(Type::Number())) {
|
| + right = BuildNumberToString(right, right_type);
|
| + } else {
|
| + ASSERT(left_type->Is(Type::String()));
|
| + HValue* function = AddLoadJSBuiltin(Builtins::STRING_ADD_LEFT);
|
| + Add<HPushArgument>(left);
|
| + Add<HPushArgument>(right);
|
| + return NewUncasted<HInvokeFunction>(function, 2);
|
| + }
|
| +
|
| + return NewUncasted<HStringAdd>(left, right, STRING_ADD_CHECK_NONE);
|
| + }
|
| +
|
| if (binop_stub) {
|
| left = EnforceNumberType(left, left_type);
|
| right = EnforceNumberType(right, right_type);
|
| @@ -7892,15 +7867,12 @@ HInstruction* HGraphBuilder::BuildBinaryOperation(
|
|
|
| bool is_non_primitive = (left_rep.IsTagged() && !left_rep.IsSmi()) ||
|
| (right_rep.IsTagged() && !right_rep.IsSmi());
|
| - bool is_string_add = op == Token::ADD &&
|
| - (left_type->Is(Type::String()) ||
|
| - right_type->Is(Type::String()));
|
|
|
| HInstruction* instr = NULL;
|
| // Only the stub is allowed to call into the runtime, since otherwise we would
|
| // inline several instructions (including the two pushes) for every tagged
|
| // operation in optimized code, which is more expensive, than a stub call.
|
| - if (binop_stub && is_non_primitive && !is_string_add) {
|
| + if (binop_stub && is_non_primitive) {
|
| HValue* function = AddLoadJSBuiltin(BinaryOpIC::TokenToJSBuiltin(op));
|
| Add<HPushArgument>(left);
|
| Add<HPushArgument>(right);
|
| @@ -7908,23 +7880,7 @@ HInstruction* HGraphBuilder::BuildBinaryOperation(
|
| } else {
|
| switch (op) {
|
| case Token::ADD:
|
| - if (is_string_add) {
|
| - StringAddFlags flags = STRING_ADD_CHECK_BOTH;
|
| - if (left_type->Is(Type::String())) {
|
| - BuildCheckHeapObject(left);
|
| - AddInstruction(HCheckInstanceType::NewIsString(left, zone()));
|
| - flags = STRING_ADD_CHECK_RIGHT;
|
| - }
|
| - if (right_type->Is(Type::String())) {
|
| - BuildCheckHeapObject(right);
|
| - AddInstruction(HCheckInstanceType::NewIsString(right, zone()));
|
| - flags = (flags == STRING_ADD_CHECK_BOTH)
|
| - ? STRING_ADD_CHECK_LEFT : STRING_ADD_CHECK_NONE;
|
| - }
|
| - instr = NewUncasted<HStringAdd>(left, right, flags);
|
| - } else {
|
| - instr = NewUncasted<HAdd>(left, right);
|
| - }
|
| + instr = NewUncasted<HAdd>(left, right);
|
| break;
|
| case Token::SUB:
|
| instr = NewUncasted<HSub>(left, right);
|
| @@ -8080,7 +8036,7 @@ void HOptimizedGraphBuilder::VisitLogicalExpression(BinaryOperation* expr) {
|
| HBranch* test = is_logical_and
|
| ? New<HBranch>(left_value, expected, eval_right, empty_block)
|
| : New<HBranch>(left_value, expected, empty_block, eval_right);
|
| - current_block()->Finish(test);
|
| + FinishCurrentBlock(test);
|
|
|
| set_current_block(eval_right);
|
| Drop(1); // Value of the left subexpression.
|
| @@ -8137,10 +8093,10 @@ void HOptimizedGraphBuilder::VisitLogicalExpression(BinaryOperation* expr) {
|
| void HOptimizedGraphBuilder::VisitArithmeticExpression(BinaryOperation* expr) {
|
| CHECK_ALIVE(VisitForValue(expr->left()));
|
| CHECK_ALIVE(VisitForValue(expr->right()));
|
| + if (!FLAG_emit_opt_code_positions) SetSourcePosition(expr->position());
|
| HValue* right = Pop();
|
| HValue* left = Pop();
|
| HInstruction* instr = BuildBinaryOperation(expr, left, right);
|
| - instr->set_position(expr->position());
|
| return ast_context()->ReturnInstruction(instr, expr->id());
|
| }
|
|
|
| @@ -8149,9 +8105,9 @@ void HOptimizedGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* expr,
|
| Expression* sub_expr,
|
| Handle<String> check) {
|
| CHECK_ALIVE(VisitForTypeOf(sub_expr));
|
| + if (!FLAG_emit_opt_code_positions) SetSourcePosition(expr->position());
|
| HValue* value = Pop();
|
| - HTypeofIsAndBranch* instr = new(zone()) HTypeofIsAndBranch(value, check);
|
| - instr->set_position(expr->position());
|
| + HTypeofIsAndBranch* instr = New<HTypeofIsAndBranch>(value, check);
|
| return ast_context()->ReturnControl(instr, expr->id());
|
| }
|
|
|
| @@ -8173,6 +8129,8 @@ void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
|
| ASSERT(current_block() != NULL);
|
| ASSERT(current_block()->HasPredecessor());
|
|
|
| + if (!FLAG_emit_opt_code_positions) SetSourcePosition(expr->position());
|
| +
|
| // Check for a few fast cases. The AST visiting behavior must be in sync
|
| // with the full codegen: We don't push both left and right values onto
|
| // the expression stack when one side is a special-case literal.
|
| @@ -8195,9 +8153,7 @@ void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
|
| HValue* value = Pop();
|
| Literal* literal = expr->right()->AsLiteral();
|
| Handle<String> rhs = Handle<String>::cast(literal->value());
|
| - HClassOfTestAndBranch* instr =
|
| - new(zone()) HClassOfTestAndBranch(value, rhs);
|
| - instr->set_position(expr->position());
|
| + HClassOfTestAndBranch* instr = New<HClassOfTestAndBranch>(value, rhs);
|
| return ast_context()->ReturnControl(instr, expr->id());
|
| }
|
|
|
| @@ -8211,7 +8167,6 @@ void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
|
| CHECK_ALIVE(VisitForValue(expr->left()));
|
| CHECK_ALIVE(VisitForValue(expr->right()));
|
|
|
| - HValue* context = environment()->context();
|
| HValue* right = Pop();
|
| HValue* left = Pop();
|
| Token::Value op = expr->op();
|
| @@ -8219,7 +8174,6 @@ void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
|
| if (IsLiteralCompareBool(isolate(), left, op, right)) {
|
| HCompareObjectEqAndBranch* result =
|
| New<HCompareObjectEqAndBranch>(left, right);
|
| - result->set_position(expr->position());
|
| return ast_context()->ReturnControl(result, expr->id());
|
| }
|
|
|
| @@ -8250,14 +8204,12 @@ void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
|
| // If the target is not null we have found a known global function that is
|
| // assumed to stay the same for this instanceof.
|
| if (target.is_null()) {
|
| - HInstanceOf* result = new(zone()) HInstanceOf(context, left, right);
|
| - result->set_position(expr->position());
|
| + HInstanceOf* result = New<HInstanceOf>(left, right);
|
| return ast_context()->ReturnInstruction(result, expr->id());
|
| } else {
|
| Add<HCheckValue>(right, target);
|
| HInstanceOfKnownGlobal* result =
|
| New<HInstanceOfKnownGlobal>(left, target);
|
| - result->set_position(expr->position());
|
| return ast_context()->ReturnInstruction(result, expr->id());
|
| }
|
|
|
| @@ -8270,7 +8222,6 @@ void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
|
| // TODO(olivf) InvokeFunction produces a check for the parameter count,
|
| // even though we are certain to pass the correct number of arguments here.
|
| HInstruction* result = New<HInvokeFunction>(function, 2);
|
| - result->set_position(expr->position());
|
| return ast_context()->ReturnInstruction(result, expr->id());
|
| }
|
|
|
| @@ -8294,16 +8245,14 @@ void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
|
| AddCheckMap(right, map);
|
| HCompareObjectEqAndBranch* result =
|
| New<HCompareObjectEqAndBranch>(left, right);
|
| - result->set_position(expr->position());
|
| return ast_context()->ReturnControl(result, expr->id());
|
| } else {
|
| BuildCheckHeapObject(left);
|
| - AddInstruction(HCheckInstanceType::NewIsSpecObject(left, zone()));
|
| + Add<HCheckInstanceType>(left, HCheckInstanceType::IS_SPEC_OBJECT);
|
| BuildCheckHeapObject(right);
|
| - AddInstruction(HCheckInstanceType::NewIsSpecObject(right, zone()));
|
| + Add<HCheckInstanceType>(right, HCheckInstanceType::IS_SPEC_OBJECT);
|
| HCompareObjectEqAndBranch* result =
|
| New<HCompareObjectEqAndBranch>(left, right);
|
| - result->set_position(expr->position());
|
| return ast_context()->ReturnControl(result, expr->id());
|
| }
|
| }
|
| @@ -8313,53 +8262,30 @@ void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
|
| } else if (combined_type->Is(Type::InternalizedString()) &&
|
| Token::IsEqualityOp(op)) {
|
| BuildCheckHeapObject(left);
|
| - AddInstruction(HCheckInstanceType::NewIsInternalizedString(left, zone()));
|
| + Add<HCheckInstanceType>(left, HCheckInstanceType::IS_INTERNALIZED_STRING);
|
| BuildCheckHeapObject(right);
|
| - AddInstruction(HCheckInstanceType::NewIsInternalizedString(right, zone()));
|
| + Add<HCheckInstanceType>(right, HCheckInstanceType::IS_INTERNALIZED_STRING);
|
| HCompareObjectEqAndBranch* result =
|
| New<HCompareObjectEqAndBranch>(left, right);
|
| - result->set_position(expr->position());
|
| return ast_context()->ReturnControl(result, expr->id());
|
| } else if (combined_type->Is(Type::String())) {
|
| BuildCheckHeapObject(left);
|
| - AddInstruction(HCheckInstanceType::NewIsString(left, zone()));
|
| + Add<HCheckInstanceType>(left, HCheckInstanceType::IS_STRING);
|
| BuildCheckHeapObject(right);
|
| - AddInstruction(HCheckInstanceType::NewIsString(right, zone()));
|
| + Add<HCheckInstanceType>(right, HCheckInstanceType::IS_STRING);
|
| HStringCompareAndBranch* result =
|
| New<HStringCompareAndBranch>(left, right, op);
|
| - result->set_position(expr->position());
|
| return ast_context()->ReturnControl(result, expr->id());
|
| - } else if (combined_type->NumClasses() == 1 && Token::IsEqualityOp(op)) {
|
| - BuildCheckHeapObject(left);
|
| - BuildCheckMap(left, combined_type->Classes().Current());
|
| - BuildCheckHeapObject(right);
|
| - BuildCheckMap(right, combined_type->Classes().Current());
|
| - HCompareObjectEqAndBranch* result =
|
| - New<HCompareObjectEqAndBranch>(left, right);
|
| - result->set_position(expr->position());
|
| - return ast_context()->ReturnInstruction(result, expr->id());
|
| - } else if (combined_type->Is(Type::Receiver()) && Token::IsEqualityOp(op)) {
|
| - BuildCheckHeapObject(left);
|
| - AddInstruction(HCheckInstanceType::NewIsSpecObject(left, zone()));
|
| - BuildCheckHeapObject(right);
|
| - AddInstruction(HCheckInstanceType::NewIsSpecObject(right, zone()));
|
| - HCompareObjectEqAndBranch* result =
|
| - New<HCompareObjectEqAndBranch>(left, right);
|
| - result->set_position(expr->position());
|
| - return ast_context()->ReturnInstruction(result, expr->id());
|
| } else {
|
| if (combined_rep.IsTagged() || combined_rep.IsNone()) {
|
| - HCompareGeneric* result =
|
| - new(zone()) HCompareGeneric(context, left, right, op);
|
| + HCompareGeneric* result = New<HCompareGeneric>(left, right, op);
|
| result->set_observed_input_representation(1, left_rep);
|
| result->set_observed_input_representation(2, right_rep);
|
| - result->set_position(expr->position());
|
| return ast_context()->ReturnInstruction(result, expr->id());
|
| } else {
|
| HCompareNumericAndBranch* result =
|
| New<HCompareNumericAndBranch>(left, right, op);
|
| result->set_observed_input_representation(left_rep, right_rep);
|
| - result->set_position(expr->position());
|
| return ast_context()->ReturnControl(result, expr->id());
|
| }
|
| }
|
| @@ -8373,6 +8299,7 @@ void HOptimizedGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr,
|
| ASSERT(current_block() != NULL);
|
| ASSERT(current_block()->HasPredecessor());
|
| ASSERT(expr->op() == Token::EQ || expr->op() == Token::EQ_STRICT);
|
| + if (!FLAG_emit_opt_code_positions) SetSourcePosition(expr->position());
|
| CHECK_ALIVE(VisitForValue(sub_expr));
|
| HValue* value = Pop();
|
| if (expr->op() == Token::EQ_STRICT) {
|
| @@ -8381,7 +8308,6 @@ void HOptimizedGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr,
|
| : graph()->GetConstantUndefined();
|
| HCompareObjectEqAndBranch* instr =
|
| New<HCompareObjectEqAndBranch>(value, nil_constant);
|
| - instr->set_position(expr->position());
|
| return ast_context()->ReturnControl(instr, expr->id());
|
| } else {
|
| ASSERT_EQ(Token::EQ, expr->op());
|
| @@ -8389,7 +8315,7 @@ void HOptimizedGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr,
|
| ? handle(Type::Any(), isolate_)
|
| : expr->combined_type();
|
| HIfContinuation continuation;
|
| - BuildCompareNil(value, type, expr->position(), &continuation);
|
| + BuildCompareNil(value, type, &continuation);
|
| return ast_context()->ReturnContinuation(&continuation, expr->id());
|
| }
|
| }
|
| @@ -8402,13 +8328,14 @@ HInstruction* HOptimizedGraphBuilder::BuildThisFunction() {
|
| return New<HConstant>(
|
| function_state()->compilation_info()->closure());
|
| } else {
|
| - return new(zone()) HThisFunction;
|
| + return New<HThisFunction>();
|
| }
|
| }
|
|
|
|
|
| HInstruction* HOptimizedGraphBuilder::BuildFastLiteral(
|
| - Handle<JSObject> boilerplate_object) {
|
| + Handle<JSObject> boilerplate_object,
|
| + AllocationSiteContext* site_context) {
|
| NoObservableSideEffectsScope no_effects(this);
|
| InstanceType instance_type = boilerplate_object->map()->instance_type();
|
| ASSERT(instance_type == JS_ARRAY_TYPE || instance_type == JS_OBJECT_TYPE);
|
| @@ -8440,15 +8367,15 @@ HInstruction* HOptimizedGraphBuilder::BuildFastLiteral(
|
| }
|
| BuildInitElementsInObjectHeader(boilerplate_object, object, object_elements);
|
|
|
| -
|
| // Copy object elements if non-COW.
|
| if (object_elements != NULL) {
|
| - BuildEmitElements(boilerplate_object, elements, object_elements);
|
| + BuildEmitElements(boilerplate_object, elements, object_elements,
|
| + site_context);
|
| }
|
|
|
| // Copy in-object properties.
|
| if (boilerplate_object->map()->NumberOfFields() != 0) {
|
| - BuildEmitInObjectProperties(boilerplate_object, object);
|
| + BuildEmitInObjectProperties(boilerplate_object, object, site_context);
|
| }
|
| return object;
|
| }
|
| @@ -8500,7 +8427,8 @@ void HOptimizedGraphBuilder::BuildInitElementsInObjectHeader(
|
|
|
| void HOptimizedGraphBuilder::BuildEmitInObjectProperties(
|
| Handle<JSObject> boilerplate_object,
|
| - HInstruction* object) {
|
| + HInstruction* object,
|
| + AllocationSiteContext* site_context) {
|
| Handle<DescriptorArray> descriptors(
|
| boilerplate_object->map()->instance_descriptors());
|
| int limit = boilerplate_object->map()->NumberOfOwnDescriptors();
|
| @@ -8524,7 +8452,10 @@ void HOptimizedGraphBuilder::BuildEmitInObjectProperties(
|
|
|
| if (value->IsJSObject()) {
|
| Handle<JSObject> value_object = Handle<JSObject>::cast(value);
|
| - HInstruction* result = BuildFastLiteral(value_object);
|
| + Handle<AllocationSite> current_site = site_context->EnterNewScope();
|
| + HInstruction* result =
|
| + BuildFastLiteral(value_object, site_context);
|
| + site_context->ExitScope(current_site, value_object);
|
| Add<HStoreNamedField>(object, access, result);
|
| } else {
|
| Representation representation = details.representation();
|
| @@ -8533,6 +8464,12 @@ void HOptimizedGraphBuilder::BuildEmitInObjectProperties(
|
| if (representation.IsDouble()) {
|
| // Allocate a HeapNumber box and store the value into it.
|
| HValue* heap_number_constant = Add<HConstant>(HeapNumber::kSize);
|
| + // TODO(mvstanton): This heap number alloc does not have a corresponding
|
| + // AllocationSite. That is okay because
|
| + // 1) it's a child object of another object with a valid allocation site
|
| + // 2) we can just use the mode of the parent object for pretenuring
|
| + // The todo is replace GetPretenureMode() with
|
| + // site_context->top()->GetPretenureMode().
|
| HInstruction* double_box =
|
| Add<HAllocate>(heap_number_constant, HType::HeapNumber(),
|
| isolate()->heap()->GetPretenureMode(), HEAP_NUMBER_TYPE);
|
| @@ -8562,7 +8499,8 @@ void HOptimizedGraphBuilder::BuildEmitInObjectProperties(
|
| void HOptimizedGraphBuilder::BuildEmitElements(
|
| Handle<JSObject> boilerplate_object,
|
| Handle<FixedArrayBase> elements,
|
| - HValue* object_elements) {
|
| + HValue* object_elements,
|
| + AllocationSiteContext* site_context) {
|
| ElementsKind kind = boilerplate_object->map()->elements_kind();
|
| int elements_length = elements->length();
|
| HValue* object_elements_length = Add<HConstant>(elements_length);
|
| @@ -8572,7 +8510,8 @@ void HOptimizedGraphBuilder::BuildEmitElements(
|
| if (elements->IsFixedDoubleArray()) {
|
| BuildEmitFixedDoubleArray(elements, kind, object_elements);
|
| } else if (elements->IsFixedArray()) {
|
| - BuildEmitFixedArray(elements, kind, object_elements);
|
| + BuildEmitFixedArray(elements, kind, object_elements,
|
| + site_context);
|
| } else {
|
| UNREACHABLE();
|
| }
|
| @@ -8601,7 +8540,8 @@ void HOptimizedGraphBuilder::BuildEmitFixedDoubleArray(
|
| void HOptimizedGraphBuilder::BuildEmitFixedArray(
|
| Handle<FixedArrayBase> elements,
|
| ElementsKind kind,
|
| - HValue* object_elements) {
|
| + HValue* object_elements,
|
| + AllocationSiteContext* site_context) {
|
| HInstruction* boilerplate_elements = Add<HConstant>(elements);
|
| int elements_length = elements->length();
|
| Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements);
|
| @@ -8610,7 +8550,10 @@ void HOptimizedGraphBuilder::BuildEmitFixedArray(
|
| HValue* key_constant = Add<HConstant>(i);
|
| if (value->IsJSObject()) {
|
| Handle<JSObject> value_object = Handle<JSObject>::cast(value);
|
| - HInstruction* result = BuildFastLiteral(value_object);
|
| + Handle<AllocationSite> current_site = site_context->EnterNewScope();
|
| + HInstruction* result =
|
| + BuildFastLiteral(value_object, site_context);
|
| + site_context->ExitScope(current_site, value_object);
|
| Add<HStoreKeyed>(object_elements, key_constant, result, kind);
|
| } else {
|
| HInstruction* value_instruction =
|
| @@ -8783,9 +8726,9 @@ void HOptimizedGraphBuilder::GenerateIsSpecObject(CallRuntime* call) {
|
| CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
|
| HValue* value = Pop();
|
| HHasInstanceTypeAndBranch* result =
|
| - new(zone()) HHasInstanceTypeAndBranch(value,
|
| - FIRST_SPEC_OBJECT_TYPE,
|
| - LAST_SPEC_OBJECT_TYPE);
|
| + New<HHasInstanceTypeAndBranch>(value,
|
| + FIRST_SPEC_OBJECT_TYPE,
|
| + LAST_SPEC_OBJECT_TYPE);
|
| return ast_context()->ReturnControl(result, call->id());
|
| }
|
|
|
| @@ -8795,7 +8738,7 @@ void HOptimizedGraphBuilder::GenerateIsFunction(CallRuntime* call) {
|
| CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
|
| HValue* value = Pop();
|
| HHasInstanceTypeAndBranch* result =
|
| - new(zone()) HHasInstanceTypeAndBranch(value, JS_FUNCTION_TYPE);
|
| + New<HHasInstanceTypeAndBranch>(value, JS_FUNCTION_TYPE);
|
| return ast_context()->ReturnControl(result, call->id());
|
| }
|
|
|
| @@ -8805,7 +8748,7 @@ void HOptimizedGraphBuilder::GenerateHasCachedArrayIndex(CallRuntime* call) {
|
| CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
|
| HValue* value = Pop();
|
| HHasCachedArrayIndexAndBranch* result =
|
| - new(zone()) HHasCachedArrayIndexAndBranch(value);
|
| + New<HHasCachedArrayIndexAndBranch>(value);
|
| return ast_context()->ReturnControl(result, call->id());
|
| }
|
|
|
| @@ -8815,7 +8758,7 @@ void HOptimizedGraphBuilder::GenerateIsArray(CallRuntime* call) {
|
| CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
|
| HValue* value = Pop();
|
| HHasInstanceTypeAndBranch* result =
|
| - new(zone()) HHasInstanceTypeAndBranch(value, JS_ARRAY_TYPE);
|
| + New<HHasInstanceTypeAndBranch>(value, JS_ARRAY_TYPE);
|
| return ast_context()->ReturnControl(result, call->id());
|
| }
|
|
|
| @@ -8825,7 +8768,7 @@ void HOptimizedGraphBuilder::GenerateIsRegExp(CallRuntime* call) {
|
| CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
|
| HValue* value = Pop();
|
| HHasInstanceTypeAndBranch* result =
|
| - new(zone()) HHasInstanceTypeAndBranch(value, JS_REGEXP_TYPE);
|
| + New<HHasInstanceTypeAndBranch>(value, JS_REGEXP_TYPE);
|
| return ast_context()->ReturnControl(result, call->id());
|
| }
|
|
|
| @@ -8869,7 +8812,7 @@ void HOptimizedGraphBuilder::GenerateIsConstructCall(CallRuntime* call) {
|
| : graph()->GetConstantFalse();
|
| return ast_context()->ReturnValue(value);
|
| } else {
|
| - return ast_context()->ReturnControl(new(zone()) HIsConstructCallAndBranch,
|
| + return ast_context()->ReturnControl(New<HIsConstructCallAndBranch>(),
|
| call->id());
|
| }
|
| }
|
| @@ -8899,8 +8842,8 @@ void HOptimizedGraphBuilder::GenerateArguments(CallRuntime* call) {
|
| HInstruction* elements = Add<HArgumentsElements>(false);
|
| HInstruction* length = Add<HArgumentsLength>(elements);
|
| HInstruction* checked_index = Add<HBoundsCheck>(index, length);
|
| - HAccessArgumentsAt* result =
|
| - new(zone()) HAccessArgumentsAt(elements, length, checked_index);
|
| + HAccessArgumentsAt* result = New<HAccessArgumentsAt>(
|
| + elements, length, checked_index);
|
| return ast_context()->ReturnInstruction(result, call->id());
|
| }
|
|
|
| @@ -8917,7 +8860,7 @@ void HOptimizedGraphBuilder::GenerateValueOf(CallRuntime* call) {
|
| ASSERT(call->arguments()->length() == 1);
|
| CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
|
| HValue* value = Pop();
|
| - HValueOf* result = new(zone()) HValueOf(value);
|
| + HValueOf* result = New<HValueOf>(value);
|
| return ast_context()->ReturnInstruction(result, call->id());
|
| }
|
|
|
| @@ -8928,7 +8871,7 @@ void HOptimizedGraphBuilder::GenerateDateField(CallRuntime* call) {
|
| Smi* index = Smi::cast(*(call->arguments()->at(1)->AsLiteral()->value()));
|
| CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
|
| HValue* date = Pop();
|
| - HDateField* result = new(zone()) HDateField(date, index);
|
| + HDateField* result = New<HDateField>(date, index);
|
| return ast_context()->ReturnInstruction(result, call->id());
|
| }
|
|
|
| @@ -8942,7 +8885,7 @@ void HOptimizedGraphBuilder::GenerateOneByteSeqStringSetChar(
|
| HValue* value = Pop();
|
| HValue* index = Pop();
|
| HValue* string = Pop();
|
| - HSeqStringSetChar* result = new(zone()) HSeqStringSetChar(
|
| + HSeqStringSetChar* result = New<HSeqStringSetChar>(
|
| String::ONE_BYTE_ENCODING, string, index, value);
|
| return ast_context()->ReturnInstruction(result, call->id());
|
| }
|
| @@ -8957,7 +8900,7 @@ void HOptimizedGraphBuilder::GenerateTwoByteSeqStringSetChar(
|
| HValue* value = Pop();
|
| HValue* index = Pop();
|
| HValue* string = Pop();
|
| - HSeqStringSetChar* result = new(zone()) HSeqStringSetChar(
|
| + HSeqStringSetChar* result = New<HSeqStringSetChar>(
|
| String::TWO_BYTE_ENCODING, string, index, value);
|
| return ast_context()->ReturnInstruction(result, call->id());
|
| }
|
| @@ -8973,25 +8916,25 @@ void HOptimizedGraphBuilder::GenerateSetValueOf(CallRuntime* call) {
|
| HBasicBlock* if_smi = graph()->CreateBasicBlock();
|
| HBasicBlock* if_heap_object = graph()->CreateBasicBlock();
|
| HBasicBlock* join = graph()->CreateBasicBlock();
|
| - current_block()->Finish(New<HIsSmiAndBranch>(object, if_smi, if_heap_object));
|
| - if_smi->Goto(join);
|
| + FinishCurrentBlock(New<HIsSmiAndBranch>(object, if_smi, if_heap_object));
|
| + Goto(if_smi, join);
|
|
|
| // Check if object is a JSValue.
|
| set_current_block(if_heap_object);
|
| HHasInstanceTypeAndBranch* typecheck =
|
| - new(zone()) HHasInstanceTypeAndBranch(object, JS_VALUE_TYPE);
|
| + New<HHasInstanceTypeAndBranch>(object, JS_VALUE_TYPE);
|
| HBasicBlock* if_js_value = graph()->CreateBasicBlock();
|
| HBasicBlock* not_js_value = graph()->CreateBasicBlock();
|
| typecheck->SetSuccessorAt(0, if_js_value);
|
| typecheck->SetSuccessorAt(1, not_js_value);
|
| - current_block()->Finish(typecheck);
|
| - not_js_value->Goto(join);
|
| + FinishCurrentBlock(typecheck);
|
| + Goto(not_js_value, join);
|
|
|
| // Create in-object property store to kValueOffset.
|
| set_current_block(if_js_value);
|
| Add<HStoreNamedField>(object,
|
| HObjectAccess::ForJSObjectOffset(JSValue::kValueOffset), value);
|
| - if_js_value->Goto(join);
|
| + Goto(if_js_value, join);
|
| join->SetJoinId(call->id());
|
| set_current_block(join);
|
| return ast_context()->ReturnValue(value);
|
| @@ -9015,7 +8958,7 @@ void HOptimizedGraphBuilder::GenerateStringCharFromCode(CallRuntime* call) {
|
| ASSERT(call->arguments()->length() == 1);
|
| CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
|
| HValue* char_code = Pop();
|
| - HInstruction* result = New<HStringCharFromCode>(char_code);
|
| + HInstruction* result = NewUncasted<HStringCharFromCode>(char_code);
|
| return ast_context()->ReturnInstruction(result, call->id());
|
| }
|
|
|
| @@ -9029,7 +8972,7 @@ void HOptimizedGraphBuilder::GenerateStringCharAt(CallRuntime* call) {
|
| HValue* string = Pop();
|
| HInstruction* char_code = BuildStringCharCodeAt(string, index);
|
| AddInstruction(char_code);
|
| - HInstruction* result = New<HStringCharFromCode>(char_code);
|
| + HInstruction* result = NewUncasted<HStringCharFromCode>(char_code);
|
| return ast_context()->ReturnInstruction(result, call->id());
|
| }
|
|
|
| @@ -9056,7 +8999,7 @@ void HOptimizedGraphBuilder::GenerateLog(CallRuntime* call) {
|
| // Fast support for Math.random().
|
| void HOptimizedGraphBuilder::GenerateRandomHeapNumber(CallRuntime* call) {
|
| HGlobalObject* global_object = Add<HGlobalObject>();
|
| - HRandom* result = new(zone()) HRandom(global_object);
|
| + HRandom* result = New<HRandom>(global_object);
|
| return ast_context()->ReturnInstruction(result, call->id());
|
| }
|
|
|
| @@ -9124,7 +9067,8 @@ void HOptimizedGraphBuilder::GenerateNumberToString(CallRuntime* call) {
|
| ASSERT_EQ(1, call->arguments()->length());
|
| CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
|
| HValue* number = Pop();
|
| - HValue* result = BuildNumberToString(number);
|
| + HValue* result = BuildNumberToString(
|
| + number, handle(Type::Number(), isolate()));
|
| return ast_context()->ReturnValue(result);
|
| }
|
|
|
| @@ -9144,25 +9088,25 @@ void HOptimizedGraphBuilder::GenerateCallFunction(CallRuntime* call) {
|
|
|
| // Branch for function proxies, or other non-functions.
|
| HHasInstanceTypeAndBranch* typecheck =
|
| - new(zone()) HHasInstanceTypeAndBranch(function, JS_FUNCTION_TYPE);
|
| + New<HHasInstanceTypeAndBranch>(function, JS_FUNCTION_TYPE);
|
| HBasicBlock* if_jsfunction = graph()->CreateBasicBlock();
|
| HBasicBlock* if_nonfunction = graph()->CreateBasicBlock();
|
| HBasicBlock* join = graph()->CreateBasicBlock();
|
| typecheck->SetSuccessorAt(0, if_jsfunction);
|
| typecheck->SetSuccessorAt(1, if_nonfunction);
|
| - current_block()->Finish(typecheck);
|
| + FinishCurrentBlock(typecheck);
|
|
|
| set_current_block(if_jsfunction);
|
| HInstruction* invoke_result = Add<HInvokeFunction>(function, arg_count);
|
| Drop(arg_count);
|
| Push(invoke_result);
|
| - if_jsfunction->Goto(join);
|
| + Goto(if_jsfunction, join);
|
|
|
| set_current_block(if_nonfunction);
|
| HInstruction* call_result = Add<HCallFunction>(function, arg_count);
|
| Drop(arg_count);
|
| Push(call_result);
|
| - if_nonfunction->Goto(join);
|
| + Goto(if_nonfunction, join);
|
|
|
| set_current_block(join);
|
| join->SetJoinId(call->id());
|
| @@ -9177,7 +9121,7 @@ void HOptimizedGraphBuilder::GenerateMathPow(CallRuntime* call) {
|
| CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
|
| HValue* right = Pop();
|
| HValue* left = Pop();
|
| - HInstruction* result = HPower::New(zone(), context(), left, right);
|
| + HInstruction* result = NewUncasted<HPower>(left, right);
|
| return ast_context()->ReturnInstruction(result, call->id());
|
| }
|
|
|
| @@ -9241,7 +9185,7 @@ void HOptimizedGraphBuilder::GenerateGetCachedArrayIndex(CallRuntime* call) {
|
| ASSERT(call->arguments()->length() == 1);
|
| CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
|
| HValue* value = Pop();
|
| - HGetCachedArrayIndex* result = new(zone()) HGetCachedArrayIndex(value);
|
| + HGetCachedArrayIndex* result = New<HGetCachedArrayIndex>(value);
|
| return ast_context()->ReturnInstruction(result, call->id());
|
| }
|
|
|
| @@ -9264,7 +9208,7 @@ void HOptimizedGraphBuilder::GenerateGeneratorThrow(CallRuntime* call) {
|
|
|
| void HOptimizedGraphBuilder::GenerateDebugBreakInOptimizedCode(
|
| CallRuntime* call) {
|
| - AddInstruction(new(zone()) HDebugBreak());
|
| + Add<HDebugBreak>();
|
| return ast_context()->ReturnValue(graph()->GetConstant0());
|
| }
|
|
|
|
|