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

Unified Diff: src/hydrogen.cc

Issue 181453002: Reset trunk to 3.24.35.4 (Closed) Base URL: https://v8.googlecode.com/svn/trunk
Patch Set: Created 6 years, 10 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-check-elimination.cc » ('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 1d437e7b4609fb2a581e53058c12b69ce92bc2b0..48ca18fe177e5b3672ebadfd287d8bc40ad66d7e 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -68,8 +68,6 @@
#include "ia32/lithium-codegen-ia32.h"
#elif V8_TARGET_ARCH_X64
#include "x64/lithium-codegen-x64.h"
-#elif V8_TARGET_ARCH_A64
-#include "a64/lithium-codegen-a64.h"
#elif V8_TARGET_ARCH_ARM
#include "arm/lithium-codegen-arm.h"
#elif V8_TARGET_ARCH_MIPS
@@ -143,13 +141,12 @@ void HBasicBlock::RemovePhi(HPhi* phi) {
}
-void HBasicBlock::AddInstruction(HInstruction* instr,
- HSourcePosition position) {
+void HBasicBlock::AddInstruction(HInstruction* instr, int position) {
ASSERT(!IsStartBlock() || !IsFinished());
ASSERT(!instr->IsLinked());
ASSERT(!IsFinished());
- if (!position.IsUnknown()) {
+ if (position != RelocInfo::kNoPosition) {
instr->set_position(position);
}
if (first_ == NULL) {
@@ -157,10 +154,10 @@ void HBasicBlock::AddInstruction(HInstruction* instr,
ASSERT(!last_environment()->ast_id().IsNone());
HBlockEntry* entry = new(zone()) HBlockEntry();
entry->InitializeAsFirst(this);
- if (!position.IsUnknown()) {
+ if (position != RelocInfo::kNoPosition) {
entry->set_position(position);
} else {
- ASSERT(!FLAG_hydrogen_track_positions ||
+ ASSERT(!FLAG_emit_opt_code_positions ||
!graph()->info()->IsOptimizing());
}
first_ = last_ = entry;
@@ -213,7 +210,7 @@ HSimulate* HBasicBlock::CreateSimulate(BailoutId ast_id,
}
-void HBasicBlock::Finish(HControlInstruction* end, HSourcePosition position) {
+void HBasicBlock::Finish(HControlInstruction* end, int position) {
ASSERT(!IsFinished());
AddInstruction(end, position);
end_ = end;
@@ -224,7 +221,7 @@ void HBasicBlock::Finish(HControlInstruction* end, HSourcePosition position) {
void HBasicBlock::Goto(HBasicBlock* block,
- HSourcePosition position,
+ int position,
FunctionState* state,
bool add_simulate) {
bool drop_extra = state != NULL &&
@@ -247,7 +244,7 @@ void HBasicBlock::Goto(HBasicBlock* block,
void HBasicBlock::AddLeaveInlined(HValue* return_value,
FunctionState* state,
- HSourcePosition position) {
+ int position) {
HBasicBlock* target = state->function_return();
bool drop_extra = state->inlining_kind() == NORMAL_RETURN;
@@ -340,15 +337,6 @@ void HBasicBlock::PostProcessLoopHeader(IterationStatement* stmt) {
}
-void HBasicBlock::MarkSuccEdgeUnreachable(int succ) {
- ASSERT(IsFinished());
- HBasicBlock* succ_block = end()->SuccessorAt(succ);
-
- ASSERT(succ_block->predecessors()->length() == 1);
- succ_block->MarkUnreachable();
-}
-
-
void HBasicBlock::RegisterPredecessor(HBasicBlock* pred) {
if (HasPredecessor()) {
// Only loop header blocks can have a predecessor added after
@@ -1044,9 +1032,9 @@ void HGraphBuilder::IfBuilder::End() {
current = merge_at_join_blocks_;
while (current != NULL) {
if (current->deopt_ && current->block_ != NULL) {
- current->block_->FinishExit(
- HAbnormalExit::New(builder_->zone(), NULL),
- HSourcePosition::Unknown());
+ builder_->PadEnvironmentForContinuation(current->block_,
+ merge_block);
+ builder_->GotoNoSimulate(current->block_, merge_block);
}
current = current->next_;
}
@@ -1179,10 +1167,9 @@ HGraph* HGraphBuilder::CreateGraph() {
HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) {
ASSERT(current_block() != NULL);
- ASSERT(!FLAG_hydrogen_track_positions ||
- !position_.IsUnknown() ||
- !info_->IsOptimizing());
- current_block()->AddInstruction(instr, source_position());
+ ASSERT(!FLAG_emit_opt_code_positions ||
+ position_ != RelocInfo::kNoPosition || !info_->IsOptimizing());
+ current_block()->AddInstruction(instr, position_);
if (graph()->IsInsideNoSideEffectsScope()) {
instr->SetFlag(HValue::kHasNoObservableSideEffects);
}
@@ -1191,10 +1178,9 @@ HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) {
void HGraphBuilder::FinishCurrentBlock(HControlInstruction* last) {
- ASSERT(!FLAG_hydrogen_track_positions ||
- !info_->IsOptimizing() ||
- !position_.IsUnknown());
- current_block()->Finish(last, source_position());
+ 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);
}
@@ -1202,9 +1188,9 @@ void HGraphBuilder::FinishCurrentBlock(HControlInstruction* last) {
void HGraphBuilder::FinishExitCurrentBlock(HControlInstruction* instruction) {
- ASSERT(!FLAG_hydrogen_track_positions || !info_->IsOptimizing() ||
- !position_.IsUnknown());
- current_block()->FinishExit(instruction, source_position());
+ 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);
}
@@ -1228,7 +1214,7 @@ void HGraphBuilder::AddSimulate(BailoutId id,
RemovableSimulate removable) {
ASSERT(current_block() != NULL);
ASSERT(!graph()->IsInsideNoSideEffectsScope());
- current_block()->AddNewSimulate(id, source_position(), removable);
+ current_block()->AddNewSimulate(id, position_, removable);
}
@@ -1254,9 +1240,38 @@ HValue* HGraphBuilder::BuildCheckHeapObject(HValue* obj) {
}
-void HGraphBuilder::FinishExitWithHardDeoptimization(const char* reason) {
+void HGraphBuilder::FinishExitWithHardDeoptimization(
+ const char* reason, HBasicBlock* continuation) {
+ PadEnvironmentForContinuation(current_block(), continuation);
Add<HDeoptimize>(reason, Deoptimizer::EAGER);
- FinishExitCurrentBlock(New<HAbnormalExit>());
+ if (graph()->IsInsideNoSideEffectsScope()) {
+ GotoNoSimulate(continuation);
+ } else {
+ Goto(continuation);
+ }
+}
+
+
+void HGraphBuilder::PadEnvironmentForContinuation(
+ HBasicBlock* from,
+ HBasicBlock* continuation) {
+ if (continuation->last_environment() != NULL) {
+ // When merging from a deopt block to a continuation, resolve differences in
+ // environment by pushing constant 0 and popping extra values so that the
+ // environments match during the join. Push 0 since it has the most specific
+ // representation, and will not influence representation inference of the
+ // phi.
+ int continuation_env_length = continuation->last_environment()->length();
+ while (continuation_env_length != from->last_environment()->length()) {
+ if (continuation_env_length > from->last_environment()->length()) {
+ from->last_environment()->Push(graph()->GetConstant0());
+ } else {
+ from->last_environment()->Pop();
+ }
+ }
+ } else {
+ ASSERT(continuation->predecessors()->length() == 0);
+ }
}
@@ -1289,14 +1304,13 @@ HValue* HGraphBuilder::BuildWrapReceiver(HValue* object, HValue* function) {
}
-HValue* HGraphBuilder::BuildCheckForCapacityGrow(
- HValue* object,
- HValue* elements,
- ElementsKind kind,
- HValue* length,
- HValue* key,
- bool is_js_array,
- PropertyAccessType access_type) {
+HValue* HGraphBuilder::BuildCheckForCapacityGrow(HValue* object,
+ HValue* elements,
+ ElementsKind kind,
+ HValue* length,
+ HValue* key,
+ bool is_js_array,
+ bool is_store) {
IfBuilder length_checker(this);
Token::Value token = IsHoleyElementsKind(kind) ? Token::GTE : Token::EQ;
@@ -1339,7 +1353,7 @@ HValue* HGraphBuilder::BuildCheckForCapacityGrow(
new_length);
}
- if (access_type == STORE && kind == FAST_SMI_ELEMENTS) {
+ if (is_store && kind == FAST_SMI_ELEMENTS) {
HValue* checked_elements = environment()->Top();
// Write zero to ensure that the new element is initialized with some smi.
@@ -1364,8 +1378,7 @@ HValue* HGraphBuilder::BuildCopyElementsOnWrite(HValue* object,
IfBuilder cow_checker(this);
- cow_checker.If<HCompareMap>(
- elements, factory->fixed_cow_array_map(), top_info());
+ cow_checker.If<HCompareMap>(elements, factory->fixed_cow_array_map());
cow_checker.Then();
HValue* capacity = AddLoadFixedArrayLength(elements);
@@ -1451,7 +1464,7 @@ HValue* HGraphBuilder::BuildUncheckedDictionaryElementLoadHelper(
HValue* candidate_key = Add<HLoadKeyed>(elements, key_index,
static_cast<HValue*>(NULL),
- FAST_ELEMENTS);
+ FAST_SMI_ELEMENTS);
IfBuilder key_compare(this);
key_compare.IfNot<HCompareObjectEqAndBranch>(key, candidate_key);
@@ -1477,7 +1490,7 @@ HValue* HGraphBuilder::BuildUncheckedDictionaryElementLoadHelper(
HValue* details = Add<HLoadKeyed>(elements, details_index,
static_cast<HValue*>(NULL),
- FAST_ELEMENTS);
+ FAST_SMI_ELEMENTS);
IfBuilder details_compare(this);
details_compare.If<HCompareNumericAndBranch>(details,
graph()->GetConstant0(),
@@ -1547,7 +1560,7 @@ HValue* HGraphBuilder::BuildUncheckedDictionaryElementLoad(HValue* receiver,
elements,
Add<HConstant>(NameDictionary::kCapacityIndex),
static_cast<HValue*>(NULL),
- FAST_ELEMENTS);
+ FAST_SMI_ELEMENTS);
HValue* mask = AddUncasted<HSub>(capacity, graph()->GetConstant1());
mask->ChangeRepresentation(Representation::Integer32());
@@ -1682,7 +1695,7 @@ HValue* HGraphBuilder::BuildNumberToString(HValue* object, Type* type) {
// Check if the object is a heap number.
IfBuilder if_objectisnumber(this);
HValue* objectisnumber = if_objectisnumber.If<HCompareMap>(
- object, isolate()->factory()->heap_number_map(), top_info());
+ object, isolate()->factory()->heap_number_map());
if_objectisnumber.Then();
{
// Compute hash for heap number similar to double_get_hash().
@@ -2146,7 +2159,7 @@ HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
HValue* val,
bool is_js_array,
ElementsKind elements_kind,
- PropertyAccessType access_type,
+ bool is_store,
LoadKeyedHoleMode load_mode,
KeyedAccessStoreMode store_mode) {
ASSERT((!IsExternalArrayElementsKind(elements_kind) &&
@@ -2159,18 +2172,18 @@ HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
// for FAST_ELEMENTS, since a transition to HOLEY elements won't change the
// generated store code.
if ((elements_kind == FAST_HOLEY_ELEMENTS) ||
- (elements_kind == FAST_ELEMENTS && access_type == STORE)) {
- checked_object->ClearDependsOnFlag(kElementsKind);
+ (elements_kind == FAST_ELEMENTS && is_store)) {
+ checked_object->ClearGVNFlag(kDependsOnElementsKind);
}
bool fast_smi_only_elements = IsFastSmiElementsKind(elements_kind);
bool fast_elements = IsFastObjectElementsKind(elements_kind);
HValue* elements = AddLoadElements(checked_object);
- if (access_type == STORE && (fast_elements || fast_smi_only_elements) &&
+ if (is_store && (fast_elements || fast_smi_only_elements) &&
store_mode != STORE_NO_TRANSITION_HANDLE_COW) {
HCheckMaps* check_cow_map = Add<HCheckMaps>(
elements, isolate()->factory()->fixed_array_map(), top_info());
- check_cow_map->ClearDependsOnFlag(kElementsKind);
+ check_cow_map->ClearGVNFlag(kDependsOnElementsKind);
}
HInstruction* length = NULL;
if (is_js_array) {
@@ -2202,7 +2215,7 @@ HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
key, graph()->GetConstant0(), Token::GTE);
negative_checker.Then();
HInstruction* result = AddElementAccess(
- backing_store, key, val, bounds_check, elements_kind, access_type);
+ backing_store, key, val, bounds_check, elements_kind, is_store);
negative_checker.ElseDeopt("Negative key encountered");
negative_checker.End();
length_checker.End();
@@ -2212,7 +2225,7 @@ HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
checked_key = Add<HBoundsCheck>(key, length);
return AddElementAccess(
backing_store, checked_key, val,
- checked_object, elements_kind, access_type);
+ checked_object, elements_kind, is_store);
}
}
ASSERT(fast_smi_only_elements ||
@@ -2222,7 +2235,7 @@ HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
// In case val is stored into a fast smi array, assure that the value is a smi
// before manipulating the backing store. Otherwise the actual store may
// deopt, leaving the backing store in an invalid state.
- if (access_type == STORE && IsFastSmiElementsKind(elements_kind) &&
+ if (is_store && IsFastSmiElementsKind(elements_kind) &&
!val->type().IsSmi()) {
val = AddUncasted<HForceRepresentation>(val, Representation::Smi());
}
@@ -2231,12 +2244,12 @@ HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
NoObservableSideEffectsScope no_effects(this);
elements = BuildCheckForCapacityGrow(checked_object, elements,
elements_kind, length, key,
- is_js_array, access_type);
+ is_js_array, is_store);
checked_key = key;
} else {
checked_key = Add<HBoundsCheck>(key, length);
- if (access_type == STORE && (fast_elements || fast_smi_only_elements)) {
+ if (is_store && (fast_elements || fast_smi_only_elements)) {
if (store_mode == STORE_NO_TRANSITION_HANDLE_COW) {
NoObservableSideEffectsScope no_effects(this);
elements = BuildCopyElementsOnWrite(checked_object, elements,
@@ -2244,12 +2257,12 @@ HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
} else {
HCheckMaps* check_cow_map = Add<HCheckMaps>(
elements, isolate()->factory()->fixed_array_map(), top_info());
- check_cow_map->ClearDependsOnFlag(kElementsKind);
+ check_cow_map->ClearGVNFlag(kDependsOnElementsKind);
}
}
}
return AddElementAccess(elements, checked_key, val, checked_object,
- elements_kind, access_type, load_mode);
+ elements_kind, is_store, load_mode);
}
@@ -2391,9 +2404,9 @@ HInstruction* HGraphBuilder::AddElementAccess(
HValue* val,
HValue* dependency,
ElementsKind elements_kind,
- PropertyAccessType access_type,
+ bool is_store,
LoadKeyedHoleMode load_mode) {
- if (access_type == STORE) {
+ if (is_store) {
ASSERT(val != NULL);
if (elements_kind == EXTERNAL_UINT8_CLAMPED_ELEMENTS ||
elements_kind == UINT8_CLAMPED_ELEMENTS) {
@@ -2405,7 +2418,7 @@ HInstruction* HGraphBuilder::AddElementAccess(
: INITIALIZING_STORE);
}
- ASSERT(access_type == LOAD);
+ ASSERT(!is_store);
ASSERT(val == NULL);
HLoadKeyed* load = Add<HLoadKeyed>(
elements, checked_key, dependency, elements_kind, load_mode);
@@ -2821,8 +2834,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()->Add<HLoadNamedField>(
- constructor_function_, static_cast<HValue*>(NULL), access);
+ return builder()->AddLoadNamedField(constructor_function_, access);
}
// TODO(mvstanton): we should always have a constructor function if we
@@ -2847,8 +2859,7 @@ HValue* HGraphBuilder::JSArrayBuilder::EmitMapCode() {
HValue* HGraphBuilder::JSArrayBuilder::EmitInternalMapCode() {
// Find the map near the constructor function
HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap();
- return builder()->Add<HLoadNamedField>(
- constructor_function_, static_cast<HValue*>(NULL), access);
+ return builder()->AddLoadNamedField(constructor_function_, access);
}
@@ -2982,7 +2993,7 @@ HValue* HGraphBuilder::AddLoadJSBuiltin(Builtins::JavaScript builtin) {
HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info)
: HGraphBuilder(info),
function_state_(NULL),
- initial_function_state_(this, info, NORMAL_RETURN, 0),
+ initial_function_state_(this, info, NORMAL_RETURN),
ast_context_(NULL),
break_scope_(NULL),
inlined_count_(0),
@@ -2994,7 +3005,7 @@ HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info)
// to know it's the initial state.
function_state_= &initial_function_state_;
InitializeAstVisitor(info->zone());
- if (FLAG_hydrogen_track_positions) {
+ if (FLAG_emit_opt_code_positions) {
SetSourcePosition(info->shared_info()->start_position());
}
}
@@ -3063,8 +3074,7 @@ HBasicBlock* HOptimizedGraphBuilder::BuildLoopEntry(
}
-void HBasicBlock::FinishExit(HControlInstruction* instruction,
- HSourcePosition position) {
+void HBasicBlock::FinishExit(HControlInstruction* instruction, int position) {
Finish(instruction, position);
ClearEnvironment();
}
@@ -3087,9 +3097,7 @@ HGraph::HGraph(CompilationInfo* info)
type_change_checksum_(0),
maximum_environment_size_(0),
no_side_effects_scope_count_(0),
- disallow_adding_new_values_(false),
- next_inline_id_(0),
- inlined_functions_(5, info->zone()) {
+ disallow_adding_new_values_(false) {
if (info->IsStub()) {
HydrogenCodeStub* stub = info->code_stub();
CodeStubInterfaceDescriptor* descriptor =
@@ -3097,7 +3105,6 @@ HGraph::HGraph(CompilationInfo* info)
start_environment_ =
new(zone_) HEnvironment(zone_, descriptor->environment_length());
} else {
- TraceInlinedFunction(info->shared_info(), HSourcePosition::Unknown());
start_environment_ =
new(zone_) HEnvironment(NULL, info->scope(), info->closure(), zone_);
}
@@ -3125,81 +3132,6 @@ void HGraph::FinalizeUniqueness() {
}
-int HGraph::TraceInlinedFunction(
- Handle<SharedFunctionInfo> shared,
- HSourcePosition position) {
- if (!FLAG_hydrogen_track_positions) {
- return 0;
- }
-
- int id = 0;
- for (; id < inlined_functions_.length(); id++) {
- if (inlined_functions_[id].shared().is_identical_to(shared)) {
- break;
- }
- }
-
- if (id == inlined_functions_.length()) {
- inlined_functions_.Add(InlinedFunctionInfo(shared), zone());
-
- if (!shared->script()->IsUndefined()) {
- Handle<Script> script(Script::cast(shared->script()));
- if (!script->source()->IsUndefined()) {
- CodeTracer::Scope tracing_scope(isolate()->GetCodeTracer());
- PrintF(tracing_scope.file(),
- "--- FUNCTION SOURCE (%s) id{%d,%d} ---\n",
- shared->DebugName()->ToCString().get(),
- info()->optimization_id(),
- id);
-
- {
- ConsStringIteratorOp op;
- StringCharacterStream stream(String::cast(script->source()),
- &op,
- shared->start_position());
- // fun->end_position() points to the last character in the stream. We
- // need to compensate by adding one to calculate the length.
- int source_len =
- shared->end_position() - shared->start_position() + 1;
- for (int i = 0; i < source_len; i++) {
- if (stream.HasMore()) {
- PrintF(tracing_scope.file(), "%c", stream.GetNext());
- }
- }
- }
-
- PrintF(tracing_scope.file(), "\n--- END ---\n");
- }
- }
- }
-
- int inline_id = next_inline_id_++;
-
- if (inline_id != 0) {
- CodeTracer::Scope tracing_scope(isolate()->GetCodeTracer());
- PrintF(tracing_scope.file(), "INLINE (%s) id{%d,%d} AS %d AT ",
- shared->DebugName()->ToCString().get(),
- info()->optimization_id(),
- id,
- inline_id);
- position.PrintTo(tracing_scope.file());
- PrintF(tracing_scope.file(), "\n");
- }
-
- return inline_id;
-}
-
-
-int HGraph::SourcePositionToScriptPosition(HSourcePosition pos) {
- if (!FLAG_hydrogen_track_positions || pos.IsUnknown()) {
- return pos.raw();
- }
-
- return inlined_functions_[pos.inlining_id()].start_position() +
- pos.position();
-}
-
-
// 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
@@ -3578,8 +3510,7 @@ void HGraph::CollectPhis() {
// a (possibly inlined) function.
FunctionState::FunctionState(HOptimizedGraphBuilder* owner,
CompilationInfo* info,
- InliningKind inlining_kind,
- int inlining_id)
+ InliningKind inlining_kind)
: owner_(owner),
compilation_info_(info),
call_context_(NULL),
@@ -3589,8 +3520,6 @@ FunctionState::FunctionState(HOptimizedGraphBuilder* owner,
entry_(NULL),
arguments_object_(NULL),
arguments_elements_(NULL),
- inlining_id_(inlining_id),
- outer_source_position_(HSourcePosition::Unknown()),
outer_(owner->function_state()) {
if (outer_ != NULL) {
// State for an inline function.
@@ -3614,27 +3543,12 @@ FunctionState::FunctionState(HOptimizedGraphBuilder* owner,
// Push on the state stack.
owner->set_function_state(this);
-
- if (FLAG_hydrogen_track_positions) {
- outer_source_position_ = owner->source_position();
- owner->EnterInlinedSource(
- info->shared_info()->start_position(),
- inlining_id);
- owner->SetSourcePosition(info->shared_info()->start_position());
- }
}
FunctionState::~FunctionState() {
delete test_context_;
owner_->set_function_state(outer_);
-
- if (FLAG_hydrogen_track_positions) {
- owner_->set_source_position(outer_source_position_);
- owner_->EnterInlinedSource(
- outer_->compilation_info()->shared_info()->start_position(),
- outer_->inlining_id());
- }
}
@@ -4447,10 +4361,8 @@ void HOptimizedGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
Type* combined_type = clause->compare_type();
HControlInstruction* compare = BuildCompareInstruction(
Token::EQ_STRICT, tag_value, label_value, tag_type, label_type,
- combined_type,
- ScriptPositionToSourcePosition(stmt->tag()->position()),
- ScriptPositionToSourcePosition(clause->label()->position()),
- PUSH_BEFORE_SIMULATE, clause->id());
+ combined_type, stmt->tag()->position(), clause->label()->position(),
+ clause->id());
HBasicBlock* next_test_block = graph()->CreateBasicBlock();
HBasicBlock* body_block = graph()->CreateBasicBlock();
@@ -4870,14 +4782,14 @@ void HOptimizedGraphBuilder::VisitConditional(Conditional* expr) {
HOptimizedGraphBuilder::GlobalPropertyAccess
HOptimizedGraphBuilder::LookupGlobalProperty(
- Variable* var, LookupResult* lookup, PropertyAccessType access_type) {
+ Variable* var, LookupResult* lookup, bool is_store) {
if (var->is_this() || !current_info()->has_global_object()) {
return kUseGeneric;
}
Handle<GlobalObject> global(current_info()->global_object());
global->Lookup(*var->name(), lookup);
if (!lookup->IsNormal() ||
- (access_type == STORE && lookup->IsReadOnly()) ||
+ (is_store && lookup->IsReadOnly()) ||
lookup->holder() != *global) {
return kUseGeneric;
}
@@ -4891,9 +4803,8 @@ HValue* HOptimizedGraphBuilder::BuildContextChainWalk(Variable* var) {
HValue* context = environment()->context();
int length = current_info()->scope()->ContextChainLength(var->scope());
while (length-- > 0) {
- context = Add<HLoadNamedField>(
- context, static_cast<HValue*>(NULL),
- HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX));
+ context = AddLoadNamedField(
+ context, HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX));
}
return context;
}
@@ -4924,7 +4835,8 @@ void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
}
LookupResult lookup(isolate());
- GlobalPropertyAccess type = LookupGlobalProperty(variable, &lookup, LOAD);
+ GlobalPropertyAccess type =
+ LookupGlobalProperty(variable, &lookup, false);
if (type == kUseCell &&
current_info()->global_object()->IsAccessCheckNeeded()) {
@@ -5159,8 +5071,7 @@ void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
HInstruction* store;
if (map.is_null()) {
// If we don't know the monomorphic type, do a generic store.
- CHECK_ALIVE(store = BuildNamedGeneric(
- STORE, literal, name, value));
+ CHECK_ALIVE(store = BuildStoreNamedGeneric(literal, name, value));
} else {
PropertyAccessInfo info(this, STORE, ToType(map), name);
if (info.CanAccessMonomorphic()) {
@@ -5170,8 +5081,8 @@ void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
&info, literal, checked_literal, value,
BailoutId::None(), BailoutId::None());
} else {
- CHECK_ALIVE(store = BuildNamedGeneric(
- STORE, literal, name, value));
+ CHECK_ALIVE(
+ store = BuildStoreNamedGeneric(literal, name, value));
}
}
AddInstruction(store);
@@ -5347,24 +5258,6 @@ HCheckMaps* HOptimizedGraphBuilder::AddCheckMap(HValue* object,
}
-HInstruction* HOptimizedGraphBuilder::BuildLoadNamedField(
- PropertyAccessInfo* info,
- HValue* checked_object) {
- HObjectAccess access = info->access();
- if (access.representation().IsDouble()) {
- // Load the heap number.
- checked_object = Add<HLoadNamedField>(
- checked_object, static_cast<HValue*>(NULL),
- access.WithRepresentation(Representation::Tagged()));
- checked_object->set_type(HType::HeapNumber());
- // Load the double value from it.
- access = HObjectAccess::ForHeapNumberValue();
- }
- return New<HLoadNamedField>(
- checked_object, static_cast<HValue*>(NULL), access);
-}
-
-
HInstruction* HOptimizedGraphBuilder::BuildStoreNamedField(
PropertyAccessInfo* info,
HValue* checked_object,
@@ -5375,7 +5268,7 @@ HInstruction* HOptimizedGraphBuilder::BuildStoreNamedField(
info->map(), info->lookup(), info->name());
HStoreNamedField *instr;
- if (field_access.representation().IsDouble()) {
+ if (FLAG_track_double_fields && field_access.representation().IsDouble()) {
HObjectAccess heap_number_access =
field_access.WithRepresentation(Representation::Tagged());
if (transition_to_field) {
@@ -5415,12 +5308,30 @@ HInstruction* HOptimizedGraphBuilder::BuildStoreNamedField(
if (transition_to_field) {
HConstant* transition_constant = Add<HConstant>(info->transition());
instr->SetTransition(transition_constant, top_info());
- instr->SetChangesFlag(kMaps);
+ instr->SetGVNFlag(kChangesMaps);
}
return instr;
}
+HInstruction* HOptimizedGraphBuilder::BuildStoreNamedGeneric(
+ HValue* object,
+ Handle<String> name,
+ HValue* value,
+ bool is_uninitialized) {
+ if (is_uninitialized) {
+ Add<HDeoptimize>("Insufficient type feedback for property assignment",
+ Deoptimizer::SOFT);
+ }
+
+ return New<HStoreNamedGeneric>(
+ object,
+ name,
+ value,
+ function_strict_mode_flag());
+}
+
+
bool HOptimizedGraphBuilder::PropertyAccessInfo::IsCompatible(
PropertyAccessInfo* info) {
if (!CanInlinePropertyAccess(type_)) return false;
@@ -5635,7 +5546,7 @@ HInstruction* HOptimizedGraphBuilder::BuildMonomorphicAccess(
if (info->lookup()->IsField()) {
if (info->IsLoad()) {
- return BuildLoadNamedField(info, checked_holder);
+ return BuildLoadNamedField(checked_holder, info->access());
} else {
return BuildStoreNamedField(info, checked_object, value);
}
@@ -5731,7 +5642,7 @@ void HOptimizedGraphBuilder::HandlePolymorphicNamedFieldAccess(
smi_check = New<HIsSmiAndBranch>(
object, empty_smi_block, not_smi_block);
FinishCurrentBlock(smi_check);
- GotoNoSimulate(empty_smi_block, number_block);
+ Goto(empty_smi_block, number_block);
set_current_block(not_smi_block);
} else {
BuildCheckHeapObject(object);
@@ -5745,22 +5656,21 @@ void HOptimizedGraphBuilder::HandlePolymorphicNamedFieldAccess(
HValue* dependency;
if (info.type()->Is(Type::Number())) {
Handle<Map> heap_number_map = isolate()->factory()->heap_number_map();
- compare = New<HCompareMap>(object, heap_number_map, top_info(),
- if_true, if_false);
+ compare = New<HCompareMap>(object, heap_number_map, if_true, if_false);
dependency = smi_check;
} else if (info.type()->Is(Type::String())) {
compare = New<HIsStringAndBranch>(object, if_true, if_false);
dependency = compare;
} else {
- compare = New<HCompareMap>(object, info.map(), top_info(),
- if_true, if_false);
+ compare = New<HCompareMap>(object, info.map(), if_true, if_false);
dependency = compare;
}
FinishCurrentBlock(compare);
if (info.type()->Is(Type::Number())) {
- GotoNoSimulate(if_true, number_block);
+ Goto(if_true, number_block);
if_true = number_block;
+ number_block->SetJoinId(ast_id);
}
set_current_block(if_true);
@@ -5794,11 +5704,32 @@ void HOptimizedGraphBuilder::HandlePolymorphicNamedFieldAccess(
// know about and do not want to handle ones we've never seen. Otherwise
// use a generic IC.
if (count == types->length() && FLAG_deoptimize_uncommon_cases) {
- FinishExitWithHardDeoptimization("Uknown map in polymorphic access");
+ // Because the deopt may be the only path in the polymorphic load, make sure
+ // that the environment stack matches the depth on deopt that it otherwise
+ // would have had after a successful load.
+ if (!ast_context()->IsEffect()) Push(graph()->GetConstant0());
+ const char* message = "";
+ switch (access_type) {
+ case LOAD:
+ message = "Unknown map in polymorphic load";
+ break;
+ case STORE:
+ message = "Unknown map in polymorphic store";
+ break;
+ }
+ FinishExitWithHardDeoptimization(message, join);
} else {
- HInstruction* instr = BuildNamedGeneric(access_type, object, name, value);
- AddInstruction(instr);
- if (!ast_context()->IsEffect()) Push(access_type == LOAD ? instr : value);
+ HValue* result = NULL;
+ switch (access_type) {
+ case LOAD:
+ result = Add<HLoadNamedGeneric>(object, name);
+ break;
+ case STORE:
+ AddInstruction(BuildStoreNamedGeneric(object, name, value));
+ result = value;
+ break;
+ }
+ if (!ast_context()->IsEffect()) Push(result);
if (join != NULL) {
Goto(join);
@@ -5810,13 +5741,9 @@ void HOptimizedGraphBuilder::HandlePolymorphicNamedFieldAccess(
}
ASSERT(join != NULL);
- if (join->HasPredecessor()) {
- join->SetJoinId(ast_id);
- set_current_block(join);
- if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
- } else {
- set_current_block(NULL);
- }
+ join->SetJoinId(ast_id);
+ set_current_block(join);
+ if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
}
@@ -5857,7 +5784,8 @@ void HOptimizedGraphBuilder::BuildStore(Expression* expr,
HValue* object = environment()->ExpressionStackAt(2);
bool has_side_effects = false;
HandleKeyedElementAccess(object, key, value, expr,
- STORE, &has_side_effects);
+ true, // is_store
+ &has_side_effects);
Drop(3);
Push(value);
Add<HSimulate>(return_id, REMOVABLE_SIMULATE);
@@ -5907,7 +5835,7 @@ void HOptimizedGraphBuilder::HandleGlobalVariableAssignment(
HValue* value,
BailoutId ast_id) {
LookupResult lookup(isolate());
- GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, STORE);
+ GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true);
if (type == kUseCell) {
Handle<GlobalObject> global(current_info()->global_object());
Handle<PropertyCell> cell(global->GetPropertyCell(&lookup));
@@ -6191,7 +6119,7 @@ void HOptimizedGraphBuilder::VisitThrow(Throw* expr) {
CHECK_ALIVE(VisitForValue(expr->exception()));
HValue* value = environment()->Pop();
- if (!FLAG_hydrogen_track_positions) SetSourcePosition(expr->position());
+ if (!FLAG_emit_opt_code_positions) SetSourcePosition(expr->position());
Add<HPushArgument>(value);
Add<HCallRuntime>(isolate()->factory()->empty_string(),
Runtime::FunctionForId(Runtime::kThrow), 1);
@@ -6206,6 +6134,29 @@ void HOptimizedGraphBuilder::VisitThrow(Throw* expr) {
}
+HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object,
+ HObjectAccess access) {
+ if (FLAG_track_double_fields && access.representation().IsDouble()) {
+ // load the heap number
+ HLoadNamedField* heap_number = Add<HLoadNamedField>(
+ object, static_cast<HValue*>(NULL),
+ access.WithRepresentation(Representation::Tagged()));
+ heap_number->set_type(HType::HeapNumber());
+ // load the double value from it
+ return New<HLoadNamedField>(
+ heap_number, static_cast<HValue*>(NULL),
+ HObjectAccess::ForHeapNumberValue());
+ }
+ return New<HLoadNamedField>(object, static_cast<HValue*>(NULL), access);
+}
+
+
+HInstruction* HGraphBuilder::AddLoadNamedField(HValue* object,
+ HObjectAccess access) {
+ return AddInstruction(BuildLoadNamedField(object, access));
+}
+
+
HInstruction* HGraphBuilder::AddLoadStringInstanceType(HValue* string) {
if (string->IsConstant()) {
HConstant* c_string = HConstant::cast(string);
@@ -6213,10 +6164,9 @@ HInstruction* HGraphBuilder::AddLoadStringInstanceType(HValue* string) {
return Add<HConstant>(c_string->StringValue()->map()->instance_type());
}
}
- return Add<HLoadNamedField>(
- Add<HLoadNamedField>(string, static_cast<HValue*>(NULL),
- HObjectAccess::ForMap()),
- static_cast<HValue*>(NULL), HObjectAccess::ForMapInstanceType());
+ return AddLoadNamedField(
+ AddLoadNamedField(string, HObjectAccess::ForMap()),
+ HObjectAccess::ForMapInstanceType());
}
@@ -6227,42 +6177,26 @@ HInstruction* HGraphBuilder::AddLoadStringLength(HValue* string) {
return Add<HConstant>(c_string->StringValue()->length());
}
}
- return Add<HLoadNamedField>(string, static_cast<HValue*>(NULL),
- HObjectAccess::ForStringLength());
+ return AddLoadNamedField(string, HObjectAccess::ForStringLength());
}
-HInstruction* HOptimizedGraphBuilder::BuildNamedGeneric(
- PropertyAccessType access_type,
+HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric(
HValue* object,
Handle<String> name,
- HValue* value,
bool is_uninitialized) {
if (is_uninitialized) {
- Add<HDeoptimize>("Insufficient type feedback for generic named access",
+ Add<HDeoptimize>("Insufficient type feedback for generic named load",
Deoptimizer::SOFT);
}
- if (access_type == LOAD) {
- return New<HLoadNamedGeneric>(object, name);
- } else {
- return New<HStoreNamedGeneric>(
- object, name, value, function_strict_mode_flag());
- }
+ return New<HLoadNamedGeneric>(object, name);
}
-HInstruction* HOptimizedGraphBuilder::BuildKeyedGeneric(
- PropertyAccessType access_type,
- HValue* object,
- HValue* key,
- HValue* value) {
- if (access_type == LOAD) {
- return New<HLoadKeyedGeneric>(object, key);
- } else {
- return New<HStoreKeyedGeneric>(
- object, key, value, function_strict_mode_flag());
- }
+HInstruction* HOptimizedGraphBuilder::BuildLoadKeyedGeneric(HValue* object,
+ HValue* key) {
+ return New<HLoadKeyedGeneric>(object, key);
}
@@ -6288,15 +6222,15 @@ HInstruction* HOptimizedGraphBuilder::BuildMonomorphicElementAccess(
HValue* val,
HValue* dependency,
Handle<Map> map,
- PropertyAccessType access_type,
+ bool is_store,
KeyedAccessStoreMode store_mode) {
HCheckMaps* checked_object = Add<HCheckMaps>(object, map, top_info(),
dependency);
if (dependency) {
- checked_object->ClearDependsOnFlag(kElementsKind);
+ checked_object->ClearGVNFlag(kDependsOnElementsKind);
}
- if (access_type == STORE && map->prototype()->IsJSObject()) {
+ if (is_store && map->prototype()->IsJSObject()) {
// monomorphic stores need a prototype chain check because shape
// changes could allow callbacks on elements in the chain that
// aren't compatible with monomorphic keyed stores.
@@ -6315,7 +6249,7 @@ HInstruction* HOptimizedGraphBuilder::BuildMonomorphicElementAccess(
return BuildUncheckedMonomorphicElementAccess(
checked_object, key, val,
map->instance_type() == JS_ARRAY_TYPE,
- map->elements_kind(), access_type,
+ map->elements_kind(), is_store,
load_mode, store_mode);
}
@@ -6371,7 +6305,7 @@ HInstruction* HOptimizedGraphBuilder::TryBuildConsolidatedElementLoad(
}
if (!has_double_maps && !has_smi_or_object_maps) return NULL;
- HCheckMaps* checked_object = Add<HCheckMaps>(object, maps, top_info());
+ HCheckMaps* checked_object = Add<HCheckMaps>(object, maps);
// FAST_ELEMENTS is considered more general than FAST_HOLEY_SMI_ELEMENTS.
// If we've seen both, the consolidated load must use FAST_HOLEY_ELEMENTS.
ElementsKind consolidated_elements_kind = has_seen_holey_elements
@@ -6381,7 +6315,7 @@ HInstruction* HOptimizedGraphBuilder::TryBuildConsolidatedElementLoad(
checked_object, key, val,
most_general_consolidated_map->instance_type() == JS_ARRAY_TYPE,
consolidated_elements_kind,
- LOAD, NEVER_RETURN_HOLE, STANDARD_STORE);
+ false, NEVER_RETURN_HOLE, STANDARD_STORE);
return instr;
}
@@ -6391,13 +6325,13 @@ HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess(
HValue* key,
HValue* val,
SmallMapList* maps,
- PropertyAccessType access_type,
+ bool is_store,
KeyedAccessStoreMode store_mode,
bool* has_side_effects) {
*has_side_effects = false;
BuildCheckHeapObject(object);
- if (access_type == LOAD) {
+ if (!is_store) {
HInstruction* consolidated_load =
TryBuildConsolidatedElementLoad(object, key, val, maps);
if (consolidated_load != NULL) {
@@ -6450,14 +6384,15 @@ HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess(
HInstruction* instr = NULL;
if (untransitionable_map->has_slow_elements_kind() ||
!untransitionable_map->IsJSObjectMap()) {
- instr = AddInstruction(BuildKeyedGeneric(access_type, object, key, val));
+ instr = AddInstruction(is_store ? BuildStoreKeyedGeneric(object, key, val)
+ : BuildLoadKeyedGeneric(object, key));
} else {
instr = BuildMonomorphicElementAccess(
- object, key, val, transition, untransitionable_map, access_type,
+ object, key, val, transition, untransitionable_map, is_store,
store_mode);
}
*has_side_effects |= instr->HasObservableSideEffects();
- return access_type == STORE ? NULL : instr;
+ return is_store ? NULL : instr;
}
HBasicBlock* join = graph()->CreateBasicBlock();
@@ -6469,13 +6404,15 @@ HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess(
HBasicBlock* this_map = graph()->CreateBasicBlock();
HBasicBlock* other_map = graph()->CreateBasicBlock();
HCompareMap* mapcompare =
- New<HCompareMap>(object, map, top_info(), this_map, other_map);
+ New<HCompareMap>(object, map, this_map, other_map);
FinishCurrentBlock(mapcompare);
set_current_block(this_map);
HInstruction* access = NULL;
if (IsDictionaryElementsKind(elements_kind)) {
- access = AddInstruction(BuildKeyedGeneric(access_type, object, key, val));
+ access = is_store
+ ? AddInstruction(BuildStoreKeyedGeneric(object, key, val))
+ : AddInstruction(BuildLoadKeyedGeneric(object, key));
} else {
ASSERT(IsFastElementsKind(elements_kind) ||
IsExternalArrayElementsKind(elements_kind));
@@ -6484,14 +6421,14 @@ HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess(
access = BuildUncheckedMonomorphicElementAccess(
mapcompare, key, val,
map->instance_type() == JS_ARRAY_TYPE,
- elements_kind, access_type,
+ elements_kind, is_store,
load_mode,
store_mode);
}
*has_side_effects |= access->HasObservableSideEffects();
// The caller will use has_side_effects and add a correct Simulate.
access->SetFlag(HValue::kHasNoObservableSideEffects);
- if (access_type == LOAD) {
+ if (!is_store) {
Push(access);
}
NoObservableSideEffectsScope scope(this);
@@ -6499,16 +6436,12 @@ HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess(
set_current_block(other_map);
}
- // Ensure that we visited at least one map above that goes to join. This is
- // necessary because FinishExitWithHardDeoptimization does an AbnormalExit
- // rather than joining the join block. If this becomes an issue, insert a
- // generic access in the case length() == 0.
- ASSERT(join->predecessors()->length() > 0);
// Deopt if none of the cases matched.
NoObservableSideEffectsScope scope(this);
- FinishExitWithHardDeoptimization("Unknown map in polymorphic element access");
+ FinishExitWithHardDeoptimization("Unknown map in polymorphic element access",
+ join);
set_current_block(join);
- return access_type == STORE ? NULL : Pop();
+ return is_store ? NULL : Pop();
}
@@ -6517,7 +6450,7 @@ HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess(
HValue* key,
HValue* val,
Expression* expr,
- PropertyAccessType access_type,
+ bool is_store,
bool* has_side_effects) {
ASSERT(!expr->IsPropertyName());
HInstruction* instr = NULL;
@@ -6526,8 +6459,7 @@ HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess(
bool monomorphic = ComputeReceiverTypes(expr, obj, &types, zone());
bool force_generic = false;
- if (access_type == STORE &&
- (monomorphic || (types != NULL && !types->is_empty()))) {
+ if (is_store && (monomorphic || (types != NULL && !types->is_empty()))) {
// Stores can't be mono/polymorphic if their prototype chain has dictionary
// elements. However a receiver map that has dictionary elements itself
// should be left to normal mono/poly behavior (the other maps may benefit
@@ -6545,36 +6477,52 @@ HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess(
if (monomorphic) {
Handle<Map> map = types->first();
if (map->has_slow_elements_kind() || !map->IsJSObjectMap()) {
- instr = AddInstruction(BuildKeyedGeneric(access_type, obj, key, val));
+ instr = is_store ? BuildStoreKeyedGeneric(obj, key, val)
+ : BuildLoadKeyedGeneric(obj, key);
+ AddInstruction(instr);
} else {
BuildCheckHeapObject(obj);
instr = BuildMonomorphicElementAccess(
- obj, key, val, NULL, map, access_type, expr->GetStoreMode());
+ obj, key, val, NULL, map, is_store, expr->GetStoreMode());
}
} else if (!force_generic && (types != NULL && !types->is_empty())) {
return HandlePolymorphicElementAccess(
- obj, key, val, types, access_type,
+ obj, key, val, types, is_store,
expr->GetStoreMode(), has_side_effects);
} else {
- if (access_type == STORE) {
+ if (is_store) {
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()->HasNoTypeInformation()) {
Add<HDeoptimize>("Insufficient type feedback for keyed load",
Deoptimizer::SOFT);
}
+ instr = BuildLoadKeyedGeneric(obj, key);
}
- instr = AddInstruction(BuildKeyedGeneric(access_type, obj, key, val));
+ AddInstruction(instr);
}
*has_side_effects = instr->HasObservableSideEffects();
return instr;
}
+HInstruction* HOptimizedGraphBuilder::BuildStoreKeyedGeneric(
+ HValue* object,
+ HValue* key,
+ HValue* value) {
+ return New<HStoreKeyedGeneric>(
+ object,
+ key,
+ value,
+ function_strict_mode_flag());
+}
+
+
void HOptimizedGraphBuilder::EnsureArgumentsArePushedForAccess() {
// Outermost function already has arguments on the stack.
if (function_state()->outer() == NULL) return;
@@ -6681,13 +6629,17 @@ HInstruction* HOptimizedGraphBuilder::BuildNamedAccess(
checked_object =
Add<HCheckInstanceType>(object, HCheckInstanceType::IS_STRING);
} else {
- checked_object = Add<HCheckMaps>(object, types, top_info());
+ checked_object = Add<HCheckMaps>(object, types);
}
return BuildMonomorphicAccess(
&info, object, checked_object, value, ast_id, return_id);
}
- return BuildNamedGeneric(access, object, name, value, is_uninitialized);
+ if (access == LOAD) {
+ return BuildLoadNamedGeneric(object, name, is_uninitialized);
+ } else {
+ return BuildStoreNamedGeneric(object, name, value, is_uninitialized);
+ }
}
@@ -6731,7 +6683,9 @@ void HOptimizedGraphBuilder::BuildLoad(Property* expr,
bool has_side_effects = false;
HValue* load = HandleKeyedElementAccess(
- obj, key, NULL, expr, LOAD, &has_side_effects);
+ obj, key, NULL, expr,
+ false, // is_store
+ &has_side_effects);
if (has_side_effects) {
if (ast_context()->IsEffect()) {
Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
@@ -6777,7 +6731,7 @@ HInstruction* HGraphBuilder::BuildConstantMapCheck(Handle<JSObject> constant,
AddInstruction(constant_value);
HCheckMaps* check =
Add<HCheckMaps>(constant_value, handle(constant->map()), info);
- check->ClearDependsOnFlag(kElementsKind);
+ check->ClearGVNFlag(kDependsOnElementsKind);
return check;
}
@@ -6861,13 +6815,44 @@ HInstruction* HOptimizedGraphBuilder::BuildCallConstantFunction(
}
+class FunctionSorter {
+ public:
+ FunctionSorter() : index_(0), ticks_(0), ast_length_(0), src_length_(0) { }
+ FunctionSorter(int index, int ticks, int ast_length, int src_length)
+ : index_(index),
+ ticks_(ticks),
+ ast_length_(ast_length),
+ src_length_(src_length) { }
+
+ int index() const { return index_; }
+ int ticks() const { return ticks_; }
+ int ast_length() const { return ast_length_; }
+ int src_length() const { return src_length_; }
+
+ private:
+ int index_;
+ int ticks_;
+ int ast_length_;
+ int src_length_;
+};
+
+
+inline bool operator<(const FunctionSorter& lhs, const FunctionSorter& rhs) {
+ int diff = lhs.ticks() - rhs.ticks();
+ if (diff != 0) return diff > 0;
+ diff = lhs.ast_length() - rhs.ast_length();
+ if (diff != 0) return diff < 0;
+ return lhs.src_length() < rhs.src_length();
+}
+
+
void HOptimizedGraphBuilder::HandlePolymorphicCallNamed(
Call* expr,
HValue* receiver,
SmallMapList* types,
Handle<String> name) {
int argument_count = expr->arguments()->length() + 1; // Includes receiver.
- int order[kMaxCallPolymorphism];
+ FunctionSorter order[kMaxCallPolymorphism];
bool handle_smi = false;
bool handled_string = false;
@@ -6889,17 +6874,23 @@ void HOptimizedGraphBuilder::HandlePolymorphicCallNamed(
handle_smi = true;
}
expr->set_target(target);
- order[ordered_functions++] = i;
+ order[ordered_functions++] =
+ FunctionSorter(i,
+ expr->target()->shared()->profiler_ticks(),
+ InliningAstSize(expr->target()),
+ expr->target()->shared()->SourceSize());
}
}
+ std::sort(order, order + ordered_functions);
+
HBasicBlock* number_block = NULL;
HBasicBlock* join = NULL;
handled_string = false;
int count = 0;
for (int fn = 0; fn < ordered_functions; ++fn) {
- int i = order[fn];
+ int i = order[fn].index();
PropertyAccessInfo info(this, LOAD, ToType(types->at(i)), name);
if (info.type()->Is(Type::String())) {
if (handled_string) continue;
@@ -6919,7 +6910,7 @@ void HOptimizedGraphBuilder::HandlePolymorphicCallNamed(
number_block = graph()->CreateBasicBlock();
FinishCurrentBlock(New<HIsSmiAndBranch>(
receiver, empty_smi_block, not_smi_block));
- GotoNoSimulate(empty_smi_block, number_block);
+ Goto(empty_smi_block, number_block);
set_current_block(not_smi_block);
} else {
BuildCheckHeapObject(receiver);
@@ -6933,19 +6924,18 @@ void HOptimizedGraphBuilder::HandlePolymorphicCallNamed(
Handle<Map> map = info.map();
if (info.type()->Is(Type::Number())) {
Handle<Map> heap_number_map = isolate()->factory()->heap_number_map();
- compare = New<HCompareMap>(receiver, heap_number_map, top_info(),
- if_true, if_false);
+ compare = New<HCompareMap>(receiver, heap_number_map, if_true, if_false);
} else if (info.type()->Is(Type::String())) {
compare = New<HIsStringAndBranch>(receiver, if_true, if_false);
} else {
- compare = New<HCompareMap>(receiver, map, top_info(),
- if_true, if_false);
+ compare = New<HCompareMap>(receiver, map, if_true, if_false);
}
FinishCurrentBlock(compare);
if (info.type()->Is(Type::Number())) {
- GotoNoSimulate(if_true, number_block);
+ Goto(if_true, number_block);
if_true = number_block;
+ number_block->SetJoinId(expr->id());
}
set_current_block(if_true);
@@ -6993,11 +6983,16 @@ void HOptimizedGraphBuilder::HandlePolymorphicCallNamed(
// know about and do not want to handle ones we've never seen. Otherwise
// use a generic IC.
if (ordered_functions == types->length() && FLAG_deoptimize_uncommon_cases) {
- FinishExitWithHardDeoptimization("Unknown map in polymorphic call");
+ // Because the deopt may be the only path in the polymorphic call, make sure
+ // that the environment stack matches the depth on deopt that it otherwise
+ // would have had after a successful call.
+ Drop(1); // Drop receiver.
+ if (!ast_context()->IsEffect()) Push(graph()->GetConstant0());
+ FinishExitWithHardDeoptimization("Unknown map in polymorphic call", join);
} else {
Property* prop = expr->expression()->AsProperty();
- HInstruction* function = BuildNamedGeneric(
- LOAD, receiver, name, NULL, prop->IsUninitialized());
+ HInstruction* function = BuildLoadNamedGeneric(
+ receiver, name, prop->IsUninitialized());
AddInstruction(function);
Push(function);
AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE);
@@ -7101,8 +7096,7 @@ bool HOptimizedGraphBuilder::TryInline(Handle<JSFunction> target,
HValue* implicit_return_value,
BailoutId ast_id,
BailoutId return_id,
- InliningKind inlining_kind,
- HSourcePosition position) {
+ InliningKind inlining_kind) {
int nodes_added = InliningAstSize(target);
if (nodes_added == kNotInlinable) return false;
@@ -7234,13 +7228,11 @@ bool HOptimizedGraphBuilder::TryInline(Handle<JSFunction> target,
ASSERT(target_shared->has_deoptimization_support());
AstTyper::Run(&target_info);
- int function_id = graph()->TraceInlinedFunction(target_shared, position);
-
// Save the pending call context. Set up new one for the inlined function.
// The function state is new-allocated because we need to delete it
// in two different places.
FunctionState* target_state = new FunctionState(
- this, &target_info, inlining_kind, function_id);
+ this, &target_info, inlining_kind);
HConstant* undefined = graph()->GetConstantUndefined();
@@ -7387,8 +7379,7 @@ bool HOptimizedGraphBuilder::TryInlineCall(Call* expr) {
NULL,
expr->id(),
expr->ReturnId(),
- NORMAL_RETURN,
- ScriptPositionToSourcePosition(expr->position()));
+ NORMAL_RETURN);
}
@@ -7399,8 +7390,7 @@ bool HOptimizedGraphBuilder::TryInlineConstruct(CallNew* expr,
implicit_return_value,
expr->id(),
expr->ReturnId(),
- CONSTRUCT_CALL_RETURN,
- ScriptPositionToSourcePosition(expr->position()));
+ CONSTRUCT_CALL_RETURN);
}
@@ -7414,8 +7404,7 @@ bool HOptimizedGraphBuilder::TryInlineGetter(Handle<JSFunction> getter,
NULL,
ast_id,
return_id,
- GETTER_CALL_RETURN,
- source_position());
+ GETTER_CALL_RETURN);
}
@@ -7429,8 +7418,7 @@ bool HOptimizedGraphBuilder::TryInlineSetter(Handle<JSFunction> setter,
1,
implicit_return_value,
id, assignment_id,
- SETTER_CALL_RETURN,
- source_position());
+ SETTER_CALL_RETURN);
}
@@ -7442,8 +7430,7 @@ bool HOptimizedGraphBuilder::TryInlineApply(Handle<JSFunction> function,
NULL,
expr->id(),
expr->ReturnId(),
- NORMAL_RETURN,
- ScriptPositionToSourcePosition(expr->position()));
+ NORMAL_RETURN);
}
@@ -7459,7 +7446,6 @@ bool HOptimizedGraphBuilder::TryInlineBuiltinFunctionCall(Call* expr) {
case kMathAbs:
case kMathSqrt:
case kMathLog:
- case kMathClz32:
if (expr->arguments()->length() == 1) {
HValue* argument = Pop();
Drop(2); // Receiver and function.
@@ -7530,7 +7516,6 @@ bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall(
case kMathAbs:
case kMathSqrt:
case kMathLog:
- case kMathClz32:
if (argument_count == 2) {
HValue* argument = Pop();
Drop(2); // Receiver and function.
@@ -7629,7 +7614,7 @@ bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall(
}
reduced_length = AddUncasted<HSub>(length, graph()->GetConstant1());
result = AddElementAccess(elements, reduced_length, NULL,
- bounds_check, elements_kind, LOAD);
+ bounds_check, elements_kind, false);
Factory* factory = isolate()->factory();
double nan_double = FixedDoubleArray::hole_nan_as_double();
HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind)
@@ -7639,7 +7624,7 @@ bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall(
elements_kind = FAST_HOLEY_ELEMENTS;
}
AddElementAccess(
- elements, reduced_length, hole, bounds_check, elements_kind, STORE);
+ elements, reduced_length, hole, bounds_check, elements_kind, true);
Add<HStoreNamedField>(
checked_object, HObjectAccess::ForArrayLength(elements_kind),
reduced_length, STORE_TO_INITIALIZED_ENTRY);
@@ -7784,12 +7769,11 @@ bool HOptimizedGraphBuilder::TryInlineApiCall(Handle<JSFunction> function,
}
bool drop_extra = false;
- bool is_store = false;
switch (call_type) {
case kCallApiFunction:
case kCallApiMethod:
// Need to check that none of the receiver maps could have changed.
- Add<HCheckMaps>(receiver, receiver_maps, top_info());
+ Add<HCheckMaps>(receiver, receiver_maps);
// Need to ensure the chain between receiver and api_holder is intact.
if (holder_lookup == CallOptimization::kHolderFound) {
AddCheckPrototypeMaps(api_holder, receiver_maps->first());
@@ -7811,7 +7795,6 @@ bool HOptimizedGraphBuilder::TryInlineApiCall(Handle<JSFunction> function,
break;
case kCallApiSetter:
{
- is_store = true;
// Receiver and prototype chain cannot have changed.
ASSERT_EQ(1, argc);
ASSERT_EQ(NULL, receiver);
@@ -7857,7 +7840,7 @@ bool HOptimizedGraphBuilder::TryInlineApiCall(Handle<JSFunction> function,
CallInterfaceDescriptor* descriptor =
isolate()->call_descriptor(Isolate::ApiFunctionCall);
- CallApiFunctionStub stub(is_store, call_data_is_undefined, argc);
+ CallApiFunctionStub stub(true, call_data_is_undefined, argc);
Handle<Code> code = stub.GetCode(isolate());
HConstant* code_value = Add<HConstant>(code);
@@ -7995,8 +7978,6 @@ void HOptimizedGraphBuilder::VisitCall(Call* expr) {
CHECK_ALIVE(PushLoad(prop, receiver, key));
HValue* function = Pop();
- if (FLAG_hydrogen_track_positions) SetSourcePosition(expr->position());
-
// Push the function under the receiver.
environment()->SetExpressionStackAt(0, function);
@@ -8059,7 +8040,7 @@ void HOptimizedGraphBuilder::VisitCall(Call* expr) {
// access check is not enabled we assume that the function will not change
// and generate optimized code for calling the function.
LookupResult lookup(isolate());
- GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, LOAD);
+ GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, false);
if (type == kUseCell &&
!current_info()->global_object()->IsAccessCheckNeeded()) {
Handle<GlobalObject> global(current_info()->global_object());
@@ -8269,7 +8250,7 @@ void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) {
ASSERT(!HasStackOverflow());
ASSERT(current_block() != NULL);
ASSERT(current_block()->HasPredecessor());
- if (!FLAG_hydrogen_track_positions) SetSourcePosition(expr->position());
+ if (!FLAG_emit_opt_code_positions) SetSourcePosition(expr->position());
int argument_count = expr->arguments()->length() + 1; // Plus constructor.
Factory* factory = isolate()->factory();
@@ -8812,7 +8793,7 @@ void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) {
ASSERT(!HasStackOverflow());
ASSERT(current_block() != NULL);
ASSERT(current_block()->HasPredecessor());
- if (!FLAG_hydrogen_track_positions) SetSourcePosition(expr->position());
+ if (!FLAG_emit_opt_code_positions) SetSourcePosition(expr->position());
Expression* target = expr->expression();
VariableProxy* proxy = target->AsVariableProxy();
Property* prop = target->AsProperty();
@@ -9088,12 +9069,13 @@ HValue* HOptimizedGraphBuilder::BuildBinaryOperation(
// after phis, which are the result of BuildBinaryOperation when we
// inlined some complex subgraph.
if (result->HasObservableSideEffects() || result->IsPhi()) {
- if (push_sim_result == PUSH_BEFORE_SIMULATE) {
- Push(result);
+ if (push_sim_result == NO_PUSH_BEFORE_SIMULATE) {
Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
- Drop(1);
} else {
+ ASSERT(push_sim_result == PUSH_BEFORE_SIMULATE);
+ Push(result);
Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
+ Drop(1);
}
}
return result;
@@ -9478,11 +9460,9 @@ void HOptimizedGraphBuilder::VisitArithmeticExpression(BinaryOperation* expr) {
BuildBinaryOperation(expr, left, right,
ast_context()->IsEffect() ? NO_PUSH_BEFORE_SIMULATE
: PUSH_BEFORE_SIMULATE);
- if (FLAG_hydrogen_track_positions && result->IsBinaryOperation()) {
+ if (FLAG_emit_opt_code_positions && result->IsBinaryOperation()) {
HBinaryOperation::cast(result)->SetOperandPositions(
- zone(),
- ScriptPositionToSourcePosition(expr->left()->position()),
- ScriptPositionToSourcePosition(expr->right()->position()));
+ zone(), expr->left()->position(), expr->right()->position());
}
return ast_context()->ReturnValue(result);
}
@@ -9516,7 +9496,7 @@ void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
ASSERT(current_block() != NULL);
ASSERT(current_block()->HasPredecessor());
- if (!FLAG_hydrogen_track_positions) SetSourcePosition(expr->position());
+ 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
@@ -9551,7 +9531,7 @@ void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
CHECK_ALIVE(VisitForValue(expr->left()));
CHECK_ALIVE(VisitForValue(expr->right()));
- if (FLAG_hydrogen_track_positions) SetSourcePosition(expr->position());
+ if (FLAG_emit_opt_code_positions) SetSourcePosition(expr->position());
HValue* right = Pop();
HValue* left = Pop();
@@ -9611,14 +9591,9 @@ void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
return ast_context()->ReturnInstruction(result, expr->id());
}
- PushBeforeSimulateBehavior push_behavior =
- ast_context()->IsEffect() ? NO_PUSH_BEFORE_SIMULATE
- : PUSH_BEFORE_SIMULATE;
HControlInstruction* compare = BuildCompareInstruction(
op, left, right, left_type, right_type, combined_type,
- ScriptPositionToSourcePosition(expr->left()->position()),
- ScriptPositionToSourcePosition(expr->right()->position()),
- push_behavior, expr->id());
+ expr->left()->position(), expr->right()->position(), expr->id());
if (compare == NULL) return; // Bailed out.
return ast_context()->ReturnControl(compare, expr->id());
}
@@ -9631,9 +9606,8 @@ HControlInstruction* HOptimizedGraphBuilder::BuildCompareInstruction(
Type* left_type,
Type* right_type,
Type* combined_type,
- HSourcePosition left_position,
- HSourcePosition right_position,
- PushBeforeSimulateBehavior push_sim_result,
+ int left_position,
+ int right_position,
BailoutId bailout_id) {
// Cases handled below depend on collected type feedback. They should
// soft deoptimize when there is no type feedback.
@@ -9658,7 +9632,7 @@ HControlInstruction* HOptimizedGraphBuilder::BuildCompareInstruction(
AddCheckMap(operand_to_check, map);
HCompareObjectEqAndBranch* result =
New<HCompareObjectEqAndBranch>(left, right);
- if (FLAG_hydrogen_track_positions) {
+ if (FLAG_emit_opt_code_positions) {
result->set_operand_position(zone(), 0, left_position);
result->set_operand_position(zone(), 1, right_position);
}
@@ -9698,13 +9672,9 @@ HControlInstruction* HOptimizedGraphBuilder::BuildCompareInstruction(
result->set_observed_input_representation(1, left_rep);
result->set_observed_input_representation(2, right_rep);
if (result->HasObservableSideEffects()) {
- if (push_sim_result == PUSH_BEFORE_SIMULATE) {
- Push(result);
- AddSimulate(bailout_id, REMOVABLE_SIMULATE);
- Drop(1);
- } else {
- AddSimulate(bailout_id, REMOVABLE_SIMULATE);
- }
+ Push(result);
+ AddSimulate(bailout_id, REMOVABLE_SIMULATE);
+ Drop(1);
}
// TODO(jkummerow): Can we make this more efficient?
HBranch* branch = New<HBranch>(result);
@@ -9713,7 +9683,7 @@ HControlInstruction* HOptimizedGraphBuilder::BuildCompareInstruction(
HCompareNumericAndBranch* result =
New<HCompareNumericAndBranch>(left, right, op);
result->set_observed_input_representation(left_rep, right_rep);
- if (FLAG_hydrogen_track_positions) {
+ if (FLAG_emit_opt_code_positions) {
result->SetOperandPositions(zone(), left_position, right_position);
}
return result;
@@ -9729,7 +9699,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_hydrogen_track_positions) SetSourcePosition(expr->position());
+ if (!FLAG_emit_opt_code_positions) SetSourcePosition(expr->position());
CHECK_ALIVE(VisitForValue(sub_expr));
HValue* value = Pop();
if (expr->op() == Token::EQ_STRICT) {
@@ -9924,12 +9894,8 @@ void HOptimizedGraphBuilder::BuildEmitInObjectProperties(
Add<HStoreNamedField>(double_box, HObjectAccess::ForHeapNumberValue(),
Add<HConstant>(value));
value_instruction = double_box;
- } else if (representation.IsSmi()) {
- value_instruction = value->IsUninitialized()
- ? graph()->GetConstant0()
- : Add<HConstant>(value);
- // Ensure that value is stored as smi.
- access = access.WithRepresentation(representation);
+ } else if (representation.IsSmi() && value->IsUninitialized()) {
+ value_instruction = graph()->GetConstant0();
} else {
value_instruction = Add<HConstant>(value);
}
@@ -10362,13 +10328,12 @@ void HOptimizedGraphBuilder::GenerateDateField(CallRuntime* call) {
void HOptimizedGraphBuilder::GenerateOneByteSeqStringSetChar(
CallRuntime* call) {
ASSERT(call->arguments()->length() == 3);
- // We need to follow the evaluation order of full codegen.
+ CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
CHECK_ALIVE(VisitForValue(call->arguments()->at(2)));
- CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
- HValue* string = Pop();
HValue* value = Pop();
HValue* index = Pop();
+ HValue* string = Pop();
Add<HSeqStringSetChar>(String::ONE_BYTE_ENCODING, string,
index, value);
Add<HSimulate>(call->id(), FIXED_SIMULATE);
@@ -10379,13 +10344,12 @@ void HOptimizedGraphBuilder::GenerateOneByteSeqStringSetChar(
void HOptimizedGraphBuilder::GenerateTwoByteSeqStringSetChar(
CallRuntime* call) {
ASSERT(call->arguments()->length() == 3);
- // We need to follow the evaluation order of full codegen.
+ CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
CHECK_ALIVE(VisitForValue(call->arguments()->at(2)));
- CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
- HValue* string = Pop();
HValue* value = Pop();
HValue* index = Pop();
+ HValue* string = Pop();
Add<HSeqStringSetChar>(String::TWO_BYTE_ENCODING, string,
index, value);
Add<HSimulate>(call->id(), FIXED_SIMULATE);
@@ -10409,23 +10373,14 @@ void HOptimizedGraphBuilder::GenerateSetValueOf(CallRuntime* call) {
Add<HStoreNamedField>(object,
HObjectAccess::ForObservableJSObjectOffset(JSValue::kValueOffset),
value);
- if (!ast_context()->IsEffect()) {
- Push(value);
- }
Add<HSimulate>(call->id(), FIXED_SIMULATE);
}
if_objectisvalue.Else();
{
// Nothing to do in this case.
- if (!ast_context()->IsEffect()) {
- Push(value);
- }
Add<HSimulate>(call->id(), FIXED_SIMULATE);
}
if_objectisvalue.End();
- if (!ast_context()->IsEffect()) {
- Drop(1);
- }
return ast_context()->ReturnValue(value);
}
@@ -10968,10 +10923,7 @@ void HTracer::TraceCompilation(CompilationInfo* info) {
if (info->IsOptimizing()) {
Handle<String> name = info->function()->debug_name();
PrintStringProperty("name", name->ToCString().get());
- PrintIndent();
- trace_.Add("method \"%s:%d\"\n",
- name->ToCString().get(),
- info->optimization_id());
+ PrintStringProperty("method", name->ToCString().get());
} else {
CodeStub::Major major_key = info->code_stub()->MajorKey();
PrintStringProperty("name", CodeStub::MajorName(major_key, false));
@@ -11085,22 +11037,14 @@ void HTracer::Trace(const char* name, HGraph* graph, LChunk* chunk) {
Tag HIR_tag(this, "HIR");
for (HInstructionIterator it(current); !it.Done(); it.Advance()) {
HInstruction* instruction = it.Current();
+ int bci = FLAG_emit_opt_code_positions && instruction->has_position() ?
+ instruction->position() : 0;
int uses = instruction->UseCount();
PrintIndent();
- trace_.Add("0 %d ", uses);
+ trace_.Add("%d %d ", bci, uses);
instruction->PrintNameTo(&trace_);
trace_.Add(" ");
instruction->PrintTo(&trace_);
- if (FLAG_hydrogen_track_positions &&
- instruction->has_position() &&
- instruction->position().raw() != 0) {
- const HSourcePosition pos = instruction->position();
- trace_.Add(" pos:");
- if (pos.inlining_id() != 0) {
- trace_.Add("%d_", pos.inlining_id());
- }
- trace_.Add("%d", pos.position());
- }
trace_.Add(" <|@\n");
}
}
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-check-elimination.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698