Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(616)

Unified Diff: src/hydrogen.cc

Issue 148153010: Synchronize with r15701. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/a64
Patch Set: Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-canonicalize.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/hydrogen.cc
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index ed2dac226fc466146a18f46faeb9de796e698620..edcc6e1b54f07ae7674e72bd33c4b92729a53cd6 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -34,15 +34,20 @@
#include "full-codegen.h"
#include "hashmap.h"
#include "hydrogen-bce.h"
+#include "hydrogen-canonicalize.h"
#include "hydrogen-dce.h"
+#include "hydrogen-dehoist.h"
+#include "hydrogen-deoptimizing-mark.h"
#include "hydrogen-environment-liveness.h"
#include "hydrogen-escape-analysis.h"
#include "hydrogen-infer-representation.h"
#include "hydrogen-infer-types.h"
#include "hydrogen-gvn.h"
+#include "hydrogen-minus-zero.h"
#include "hydrogen-osr.h"
#include "hydrogen-range-analysis.h"
#include "hydrogen-redundant-phi.h"
+#include "hydrogen-removable-simulates.h"
#include "hydrogen-representation-changes.h"
#include "hydrogen-sce.h"
#include "hydrogen-uint32-analysis.h"
@@ -1144,21 +1149,22 @@ HValue* HGraphBuilder::BuildCheckForCapacityGrow(HValue* object,
Zone* zone = this->zone();
IfBuilder length_checker(this);
- length_checker.If<HCompareNumericAndBranch>(length, key, Token::EQ);
+ Token::Value token = IsHoleyElementsKind(kind) ? Token::GTE : Token::EQ;
+ length_checker.If<HCompareNumericAndBranch>(key, length, token);
+
length_checker.Then();
HValue* current_capacity = AddLoadFixedArrayLength(elements);
IfBuilder capacity_checker(this);
- capacity_checker.If<HCompareNumericAndBranch>(length, current_capacity,
- Token::EQ);
+ capacity_checker.If<HCompareNumericAndBranch>(key, current_capacity,
+ Token::GTE);
capacity_checker.Then();
HValue* context = environment()->LookupContext();
- HValue* new_capacity =
- BuildNewElementsCapacity(context, current_capacity);
+ HValue* new_capacity = BuildNewElementsCapacity(context, key);
HValue* new_elements = BuildGrowElementsCapacity(object, elements,
kind, kind, length,
@@ -1172,7 +1178,7 @@ HValue* HGraphBuilder::BuildCheckForCapacityGrow(HValue* object,
if (is_js_array) {
HValue* new_length = AddInstruction(
- HAdd::New(zone, context, length, graph_->GetConstant1()));
+ HAdd::New(zone, context, key, graph_->GetConstant1()));
new_length->ClearFlag(HValue::kCanOverflow);
Representation representation = IsFastElementsKind(kind)
@@ -1182,10 +1188,9 @@ HValue* HGraphBuilder::BuildCheckForCapacityGrow(HValue* object,
}
length_checker.Else();
-
Add<HBoundsCheck>(key, length);
- environment()->Push(elements);
+ environment()->Push(elements);
length_checker.End();
return environment()->Pop();
@@ -2091,33 +2096,6 @@ void HGraph::FinalizeUniqueValueIds() {
}
-void HGraph::Canonicalize() {
- HPhase phase("H_Canonicalize", this);
- // Before removing no-op instructions, save their semantic value.
- // We must be careful not to set the flag unnecessarily, because GVN
- // cannot identify two instructions when their flag value differs.
- for (int i = 0; i < blocks()->length(); ++i) {
- for (HInstructionIterator it(blocks()->at(i)); !it.Done(); it.Advance()) {
- HInstruction* instr = it.Current();
- if (instr->IsArithmeticBinaryOperation() &&
- instr->representation().IsInteger32() &&
- instr->HasAtLeastOneUseWithFlagAndNoneWithout(
- HInstruction::kTruncatingToInt32)) {
- instr->SetFlag(HInstruction::kAllUsesTruncatingToInt32);
- }
- }
- }
- // Perform actual Canonicalization pass.
- for (int i = 0; i < blocks()->length(); ++i) {
- for (HInstructionIterator it(blocks()->at(i)); !it.Done(); it.Advance()) {
- HInstruction* instr = it.Current();
- HValue* value = instr->Canonicalize();
- if (value != instr) instr->DeleteAndReplaceWith(value);
- }
- }
-}
-
-
// Block ordering was implemented with two mutually recursive methods,
// HGraph::Postorder and HGraph::PostorderLoopBlocks.
// The recursion could lead to stack overflow so the algorithm has been
@@ -2452,87 +2430,6 @@ void HGraph::AssignDominators() {
}
-// Mark all blocks that are dominated by an unconditional soft deoptimize to
-// prevent code motion across those blocks.
-void HGraph::PropagateDeoptimizingMark() {
- HPhase phase("H_Propagate deoptimizing mark", this);
- // Skip this phase if there is nothing to be done anyway.
- if (!has_soft_deoptimize()) return;
- MarkAsDeoptimizingRecursively(entry_block());
- NullifyUnreachableInstructions();
-}
-
-
-void HGraph::MarkAsDeoptimizingRecursively(HBasicBlock* block) {
- for (int i = 0; i < block->dominated_blocks()->length(); ++i) {
- HBasicBlock* dominated = block->dominated_blocks()->at(i);
- if (block->IsDeoptimizing()) dominated->MarkAsDeoptimizing();
- MarkAsDeoptimizingRecursively(dominated);
- }
-}
-
-
-void HGraph::NullifyUnreachableInstructions() {
- if (!FLAG_unreachable_code_elimination) return;
- int block_count = blocks_.length();
- for (int i = 0; i < block_count; ++i) {
- HBasicBlock* block = blocks_.at(i);
- bool nullify = false;
- const ZoneList<HBasicBlock*>* predecessors = block->predecessors();
- int predecessors_length = predecessors->length();
- bool all_predecessors_deoptimizing = (predecessors_length > 0);
- for (int j = 0; j < predecessors_length; ++j) {
- if (!predecessors->at(j)->IsDeoptimizing()) {
- all_predecessors_deoptimizing = false;
- break;
- }
- }
- if (all_predecessors_deoptimizing) nullify = true;
- for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
- HInstruction* instr = it.Current();
- // Leave the basic structure of the graph intact.
- if (instr->IsBlockEntry()) continue;
- if (instr->IsControlInstruction()) continue;
- if (instr->IsSimulate()) continue;
- if (instr->IsEnterInlined()) continue;
- if (instr->IsLeaveInlined()) continue;
- if (nullify) {
- HInstruction* last_dummy = NULL;
- for (int j = 0; j < instr->OperandCount(); ++j) {
- HValue* operand = instr->OperandAt(j);
- // Insert an HDummyUse for each operand, unless the operand
- // is an HDummyUse itself. If it's even from the same block,
- // remember it as a potential replacement for the instruction.
- if (operand->IsDummyUse()) {
- if (operand->block() == instr->block() &&
- last_dummy == NULL) {
- last_dummy = HInstruction::cast(operand);
- }
- continue;
- }
- if (operand->IsControlInstruction()) {
- // Inserting a dummy use for a value that's not defined anywhere
- // will fail. Some instructions define fake inputs on such
- // values as control flow dependencies.
- continue;
- }
- HDummyUse* dummy = new(zone()) HDummyUse(operand);
- dummy->InsertBefore(instr);
- last_dummy = dummy;
- }
- if (last_dummy == NULL) last_dummy = GetConstant1();
- instr->DeleteAndReplaceWith(last_dummy);
- continue;
- }
- if (instr->IsSoftDeoptimize()) {
- ASSERT(block->IsDeoptimizing());
- nullify = true;
- }
- }
- }
-}
-
-
bool HGraph::CheckArgumentsPhiUses() {
int block_count = blocks_.length();
for (int i = 0; i < block_count; ++i) {
@@ -2573,108 +2470,6 @@ void HGraph::CollectPhis() {
}
-void HGraph::MergeRemovableSimulates() {
- HPhase phase("H_Merge removable simulates", this);
- ZoneList<HSimulate*> mergelist(2, zone());
- for (int i = 0; i < blocks()->length(); ++i) {
- HBasicBlock* block = blocks()->at(i);
- // Make sure the merge list is empty at the start of a block.
- ASSERT(mergelist.is_empty());
- // Nasty heuristic: Never remove the first simulate in a block. This
- // just so happens to have a beneficial effect on register allocation.
- bool first = true;
- for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
- HInstruction* current = it.Current();
- if (current->IsLeaveInlined()) {
- // Never fold simulates from inlined environments into simulates
- // in the outer environment.
- // (Before each HEnterInlined, there is a non-foldable HSimulate
- // anyway, so we get the barrier in the other direction for free.)
- // Simply remove all accumulated simulates without merging. This
- // is safe because simulates after instructions with side effects
- // are never added to the merge list.
- while (!mergelist.is_empty()) {
- mergelist.RemoveLast()->DeleteAndReplaceWith(NULL);
- }
- continue;
- }
- if (current->IsReturn()) {
- // Drop mergeable simulates in the list. This is safe because
- // simulates after instructions with side effects are never added
- // to the merge list.
- while (!mergelist.is_empty()) {
- mergelist.RemoveLast()->DeleteAndReplaceWith(NULL);
- }
- continue;
- }
- // Skip the non-simulates and the first simulate.
- if (!current->IsSimulate()) continue;
- if (first) {
- first = false;
- continue;
- }
- HSimulate* current_simulate = HSimulate::cast(current);
- if ((current_simulate->previous()->HasObservableSideEffects() &&
- !current_simulate->next()->IsSimulate()) ||
- !current_simulate->is_candidate_for_removal()) {
- // This simulate is not suitable for folding.
- // Fold the ones accumulated so far.
- current_simulate->MergeWith(&mergelist);
- continue;
- } else {
- // Accumulate this simulate for folding later on.
- mergelist.Add(current_simulate, zone());
- }
- }
-
- if (!mergelist.is_empty()) {
- // Merge the accumulated simulates at the end of the block.
- HSimulate* last = mergelist.RemoveLast();
- last->MergeWith(&mergelist);
- }
- }
-}
-
-
-void HGraph::PropagateMinusZeroChecks(HValue* value, BitVector* visited) {
- HValue* current = value;
- while (current != NULL) {
- if (visited->Contains(current->id())) return;
-
- // For phis, we must propagate the check to all of its inputs.
- if (current->IsPhi()) {
- visited->Add(current->id());
- HPhi* phi = HPhi::cast(current);
- for (int i = 0; i < phi->OperandCount(); ++i) {
- PropagateMinusZeroChecks(phi->OperandAt(i), visited);
- }
- break;
- }
-
- // For multiplication, division, and Math.min/max(), we must propagate
- // to the left and the right side.
- if (current->IsMul()) {
- HMul* mul = HMul::cast(current);
- mul->EnsureAndPropagateNotMinusZero(visited);
- PropagateMinusZeroChecks(mul->left(), visited);
- PropagateMinusZeroChecks(mul->right(), visited);
- } else if (current->IsDiv()) {
- HDiv* div = HDiv::cast(current);
- div->EnsureAndPropagateNotMinusZero(visited);
- PropagateMinusZeroChecks(div->left(), visited);
- PropagateMinusZeroChecks(div->right(), visited);
- } else if (current->IsMathMinMax()) {
- HMathMinMax* minmax = HMathMinMax::cast(current);
- visited->Add(minmax->id());
- PropagateMinusZeroChecks(minmax->left(), visited);
- PropagateMinusZeroChecks(minmax->right(), visited);
- }
-
- current = current->EnsureAndPropagateNotMinusZero(visited);
- }
-}
-
-
void HGraph::RecursivelyMarkPhiDeoptimizeOnUndefined(HPhi* phi) {
if (!phi->CheckFlag(HValue::kAllowUndefinedAsNaN)) return;
phi->ClearFlag(HValue::kAllowUndefinedAsNaN);
@@ -2707,32 +2502,6 @@ void HGraph::MarkDeoptimizeOnUndefined() {
}
-void HGraph::ComputeMinusZeroChecks() {
- HPhase phase("H_Compute minus zero checks", this);
- BitVector visited(GetMaximumValueID(), zone());
- for (int i = 0; i < blocks_.length(); ++i) {
- for (HInstructionIterator it(blocks_[i]); !it.Done(); it.Advance()) {
- HInstruction* current = it.Current();
- if (current->IsChange()) {
- HChange* change = HChange::cast(current);
- // Propagate flags for negative zero checks upwards from conversions
- // int32-to-tagged and int32-to-double.
- Representation from = change->value()->representation();
- ASSERT(from.Equals(change->from()));
- if (from.IsInteger32()) {
- ASSERT(change->to().IsTagged() ||
- change->to().IsDouble() ||
- change->to().IsSmi());
- ASSERT(visited.IsEmpty());
- PropagateMinusZeroChecks(change->value(), &visited);
- visited.Clear();
- }
- }
- }
- }
-}
-
-
// Implementation of utility class to encapsulate the translation state for
// a (possibly inlined) function.
FunctionState::FunctionState(HOptimizedGraphBuilder* owner,
@@ -3179,7 +2948,7 @@ bool HGraph::Optimize(SmartArrayPointer<char>* bailout_reason) {
Run<HEnvironmentLivenessAnalysisPhase>();
}
- PropagateDeoptimizingMark();
+ Run<HPropagateDeoptimizingMarkPhase>();
if (!CheckConstPhiUses()) {
*bailout_reason = SmartArrayPointer<char>(StrDup(
"Unsupported phi use of const variable"));
@@ -3203,7 +2972,7 @@ bool HGraph::Optimize(SmartArrayPointer<char>* bailout_reason) {
// Remove HSimulate instructions that have turned out not to be needed
// after all by folding them into the following HSimulate.
// This must happen after inferring representations.
- MergeRemovableSimulates();
+ Run<HMergeRemovableSimulatesPhase>();
MarkDeoptimizeOnUndefined();
Run<HRepresentationChangesPhase>();
@@ -3215,7 +2984,7 @@ bool HGraph::Optimize(SmartArrayPointer<char>* bailout_reason) {
// zero.
if (FLAG_opt_safe_uint32_operations) Run<HUint32AnalysisPhase>();
- if (FLAG_use_canonicalizing) Canonicalize();
+ if (FLAG_use_canonicalizing) Run<HCanonicalizePhase>();
if (FLAG_use_escape_analysis) Run<HEscapeAnalysisPhase>();
@@ -3223,7 +2992,7 @@ bool HGraph::Optimize(SmartArrayPointer<char>* bailout_reason) {
if (FLAG_use_range) Run<HRangeAnalysisPhase>();
- ComputeMinusZeroChecks();
+ Run<HComputeMinusZeroChecksPhase>();
// Eliminate redundant stack checks on backwards branches.
Run<HStackCheckEliminationPhase>();
@@ -3232,7 +3001,7 @@ bool HGraph::Optimize(SmartArrayPointer<char>* bailout_reason) {
if (FLAG_array_bounds_checks_elimination && !FLAG_idefs) {
Run<HBoundsCheckEliminationPhase>();
}
- if (FLAG_array_index_dehoisting) DehoistSimpleArrayIndexComputations();
+ if (FLAG_array_index_dehoisting) Run<HDehoistIndexComputationsPhase>();
if (FLAG_dead_code_elimination) Run<HDeadCodeEliminationPhase>();
RestoreActualValues();
@@ -3285,77 +3054,6 @@ void HGraph::SetupInformativeDefinitions() {
}
-static void DehoistArrayIndex(ArrayInstructionInterface* array_operation) {
- HValue* index = array_operation->GetKey()->ActualValue();
- if (!index->representation().IsSmiOrInteger32()) return;
-
- HConstant* constant;
- HValue* subexpression;
- int32_t sign;
- if (index->IsAdd()) {
- sign = 1;
- HAdd* add = HAdd::cast(index);
- if (add->left()->IsConstant()) {
- subexpression = add->right();
- constant = HConstant::cast(add->left());
- } else if (add->right()->IsConstant()) {
- subexpression = add->left();
- constant = HConstant::cast(add->right());
- } else {
- return;
- }
- } else if (index->IsSub()) {
- sign = -1;
- HSub* sub = HSub::cast(index);
- if (sub->left()->IsConstant()) {
- subexpression = sub->right();
- constant = HConstant::cast(sub->left());
- } else if (sub->right()->IsConstant()) {
- subexpression = sub->left();
- constant = HConstant::cast(sub->right());
- } else {
- return;
- }
- } else {
- return;
- }
-
- if (!constant->HasInteger32Value()) return;
- int32_t value = constant->Integer32Value() * sign;
- // We limit offset values to 30 bits because we want to avoid the risk of
- // overflows when the offset is added to the object header size.
- if (value >= 1 << 30 || value < 0) return;
- array_operation->SetKey(subexpression);
- if (index->HasNoUses()) {
- index->DeleteAndReplaceWith(NULL);
- }
- ASSERT(value >= 0);
- array_operation->SetIndexOffset(static_cast<uint32_t>(value));
- array_operation->SetDehoisted(true);
-}
-
-
-void HGraph::DehoistSimpleArrayIndexComputations() {
- HPhase phase("H_Dehoist index computations", this);
- for (int i = 0; i < blocks()->length(); ++i) {
- for (HInstructionIterator it(blocks()->at(i)); !it.Done(); it.Advance()) {
- HInstruction* instr = it.Current();
- ArrayInstructionInterface* array_instruction = NULL;
- if (instr->IsLoadKeyed()) {
- HLoadKeyed* op = HLoadKeyed::cast(instr);
- array_instruction = static_cast<ArrayInstructionInterface*>(op);
- } else if (instr->IsStoreKeyed()) {
- HStoreKeyed* op = HStoreKeyed::cast(instr);
- array_instruction = static_cast<ArrayInstructionInterface*>(op);
- } else {
- continue;
- }
- DehoistArrayIndex(array_instruction);
- }
- }
-}
-
-
void HGraph::RestoreActualValues() {
HPhase phase("H_Restore actual values", this);
@@ -4915,19 +4613,6 @@ HInstruction* HOptimizedGraphBuilder::BuildStoreNamedGeneric(
}
-HInstruction* HOptimizedGraphBuilder::BuildCallSetter(
- HValue* object,
- HValue* value,
- Handle<Map> map,
- Handle<JSFunction> setter,
- Handle<JSObject> holder) {
- AddCheckConstantFunction(holder, object, map);
- Add<HPushArgument>(object);
- Add<HPushArgument>(value);
- return new(zone()) HCallConstantFunction(setter, 2);
-}
-
-
HInstruction* HOptimizedGraphBuilder::BuildStoreNamedMonomorphic(
HValue* object,
Handle<String> name,
@@ -6124,8 +5809,14 @@ HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess(
expr->GetStoreMode(), has_side_effects);
} else {
if (is_store) {
+ if (expr->IsAssignment() && expr->AsAssignment()->IsUninitialized()) {
+ AddSoftDeoptimize();
+ }
instr = BuildStoreKeyedGeneric(obj, key, val);
} else {
+ if (expr->AsProperty()->IsUninitialized()) {
+ AddSoftDeoptimize();
+ }
instr = BuildLoadKeyedGeneric(obj, key);
}
AddInstruction(instr);
@@ -7428,12 +7119,11 @@ void HOptimizedGraphBuilder::VisitCall(Call* expr) {
} else {
VariableProxy* proxy = expr->expression()->AsVariableProxy();
- bool global_call = proxy != NULL && proxy->var()->IsUnallocated();
-
if (proxy != NULL && proxy->var()->is_possibly_eval(isolate())) {
return Bailout("possible direct call to eval");
}
+ bool global_call = proxy != NULL && proxy->var()->IsUnallocated();
if (global_call) {
Variable* var = proxy->var();
bool known_global_function = false;
@@ -7556,7 +7246,8 @@ void HOptimizedGraphBuilder::VisitCall(Call* expr) {
static bool IsAllocationInlineable(Handle<JSFunction> constructor) {
return constructor->has_initial_map() &&
constructor->initial_map()->instance_type() == JS_OBJECT_TYPE &&
- constructor->initial_map()->instance_size() < HAllocateObject::kMaxSize;
+ constructor->initial_map()->instance_size() < HAllocate::kMaxInlineSize &&
+ constructor->initial_map()->InitialPropertiesLength() == 0;
}
@@ -7566,6 +7257,7 @@ void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) {
ASSERT(current_block()->HasPredecessor());
int argument_count = expr->arguments()->length() + 1; // Plus constructor.
HValue* context = environment()->LookupContext();
+ Factory* factory = isolate()->factory();
if (FLAG_inline_construct &&
expr->IsMonomorphic() &&
@@ -7584,19 +7276,73 @@ void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) {
constructor->shared()->CompleteInobjectSlackTracking();
}
- // Replace the constructor function with a newly allocated receiver.
- HInstruction* receiver = Add<HAllocateObject>(context, constructor);
- // Index of the receiver from the top of the expression stack.
+ // Calculate instance size from initial map of constructor.
+ ASSERT(constructor->has_initial_map());
+ Handle<Map> initial_map(constructor->initial_map());
+ int instance_size = initial_map->instance_size();
+ ASSERT(initial_map->InitialPropertiesLength() == 0);
+
+ // Allocate an instance of the implicit receiver object.
+ HValue* size_in_bytes = Add<HConstant>(instance_size);
+ HAllocate::Flags flags = HAllocate::DefaultFlags();
+ if (FLAG_pretenuring_call_new &&
+ isolate()->heap()->ShouldGloballyPretenure()) {
+ flags = static_cast<HAllocate::Flags>(
+ flags | HAllocate::CAN_ALLOCATE_IN_OLD_POINTER_SPACE);
+ }
+ HAllocate* receiver =
+ Add<HAllocate>(context, size_in_bytes, HType::JSObject(), flags);
+ receiver->set_known_initial_map(initial_map);
+
+ // Load the initial map from the constructor.
+ HValue* constructor_value = Add<HConstant>(constructor);
+ HValue* initial_map_value =
+ AddLoad(constructor_value, HObjectAccess::ForJSObjectOffset(
+ JSFunction::kPrototypeOrInitialMapOffset));
+
+ // Initialize map and fields of the newly allocated object.
+ { NoObservableSideEffectsScope no_effects(this);
+ ASSERT(initial_map->instance_type() == JS_OBJECT_TYPE);
+ AddStore(receiver,
+ HObjectAccess::ForJSObjectOffset(JSObject::kMapOffset),
+ initial_map_value);
+ HValue* empty_fixed_array = Add<HConstant>(factory->empty_fixed_array());
+ AddStore(receiver,
+ HObjectAccess::ForJSObjectOffset(JSObject::kPropertiesOffset),
+ empty_fixed_array);
+ AddStore(receiver,
+ HObjectAccess::ForJSObjectOffset(JSObject::kElementsOffset),
+ empty_fixed_array);
+ if (initial_map->inobject_properties() != 0) {
+ HConstant* undefined = graph()->GetConstantUndefined();
+ for (int i = 0; i < initial_map->inobject_properties(); i++) {
+ int property_offset = JSObject::kHeaderSize + i * kPointerSize;
+ AddStore(receiver,
+ HObjectAccess::ForJSObjectOffset(property_offset),
+ undefined);
+ }
+ }
+ }
+
+ // Replace the constructor function with a newly allocated receiver using
+ // the index of the receiver from the top of the expression stack.
const int receiver_index = argument_count - 1;
ASSERT(environment()->ExpressionStackAt(receiver_index) == function);
environment()->SetExpressionStackAt(receiver_index, receiver);
if (TryInlineConstruct(expr, receiver)) return;
- // TODO(mstarzinger): For now we remove the previous HAllocateObject and
- // add HPushArgument for the arguments in case inlining failed. What we
- // actually should do is emit HInvokeFunction on the constructor instead
- // of using HCallNew as a fallback.
+ // TODO(mstarzinger): For now we remove the previous HAllocate and all
+ // corresponding instructions and instead add HPushArgument for the
+ // arguments in case inlining failed. What we actually should do is for
+ // inlining to try to build a subgraph without mutating the parent graph.
+ HInstruction* instr = current_block()->last();
+ while (instr != initial_map_value) {
+ HInstruction* prev_instr = instr->previous();
+ instr->DeleteAndReplaceWith(NULL);
+ instr = prev_instr;
+ }
+ initial_map_value->DeleteAndReplaceWith(NULL);
receiver->DeleteAndReplaceWith(NULL);
check->DeleteAndReplaceWith(NULL);
environment()->SetExpressionStackAt(receiver_index, function);
@@ -7654,6 +7400,14 @@ void HOptimizedGraphBuilder::VisitCallRuntime(CallRuntime* expr) {
const Runtime::Function* function = expr->function();
ASSERT(function != NULL);
+
+ if (static_cast<int>(function->function_id)
+ == static_cast<int>(Runtime::kNeverOptimize)
+ && expr->arguments()->length() == 0) {
+ // %NeverOptimize() without arguments marks the caller as never optimize.
+ return Bailout("function marked itself as never optimize");
+ }
+
if (function->intrinsic_type == Runtime::INLINE) {
ASSERT(expr->name()->length() > 0);
ASSERT(expr->name()->Get(0) == '_');
@@ -7757,7 +7511,7 @@ void HOptimizedGraphBuilder::VisitTypeof(UnaryOperation* expr) {
void HOptimizedGraphBuilder::VisitSub(UnaryOperation* expr) {
CHECK_ALIVE(VisitForValue(expr->expression()));
HValue* value = Pop();
- Handle<Type> operand_type = expr->expression()->lower_type();
+ Handle<Type> operand_type = expr->expression()->bounds().lower;
HInstruction* instr = BuildUnaryMathOp(value, operand_type, Token::SUB);
return ast_context()->ReturnInstruction(instr, expr->id());
}
@@ -7766,7 +7520,7 @@ void HOptimizedGraphBuilder::VisitSub(UnaryOperation* expr) {
void HOptimizedGraphBuilder::VisitBitNot(UnaryOperation* expr) {
CHECK_ALIVE(VisitForValue(expr->expression()));
HValue* value = Pop();
- Handle<Type> operand_type = expr->expression()->lower_type();
+ Handle<Type> operand_type = expr->expression()->bounds().lower;
HInstruction* instr = BuildUnaryMathOp(value, operand_type, Token::BIT_NOT);
return ast_context()->ReturnInstruction(instr, expr->id());
}
@@ -8102,9 +7856,9 @@ HInstruction* HOptimizedGraphBuilder::BuildBinaryOperation(
HValue* left,
HValue* right) {
HValue* context = environment()->LookupContext();
- Handle<Type> left_type = expr->left()->lower_type();
- Handle<Type> right_type = expr->right()->lower_type();
- Handle<Type> result_type = expr->lower_type();
+ Handle<Type> left_type = expr->left()->bounds().lower;
+ Handle<Type> right_type = expr->right()->bounds().lower;
+ Handle<Type> result_type = expr->bounds().lower;
Maybe<int> fixed_right_arg = expr->fixed_right_arg();
Representation left_rep = Representation::FromType(left_type);
Representation right_rep = Representation::FromType(right_type);
@@ -8426,8 +8180,8 @@ void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
return ast_context()->ReturnControl(instr, expr->id());
}
- Handle<Type> left_type = expr->left()->lower_type();
- Handle<Type> right_type = expr->right()->lower_type();
+ Handle<Type> left_type = expr->left()->bounds().lower;
+ Handle<Type> right_type = expr->right()->bounds().lower;
Handle<Type> combined_type = expr->combined_type();
Representation combined_rep = Representation::FromType(combined_type);
Representation left_rep = Representation::FromType(left_type);
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-canonicalize.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698