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

Unified Diff: src/hydrogen.cc

Issue 12221064: Implement many KeyedStoreStubs using Crankshaft (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Rebase Created 7 years, 9 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
Index: src/hydrogen.cc
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index c2f3951494e647936183cdb1d25659c8d5ee187f..d18c8449f10304238d67029c3d985dd347a86917 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -114,6 +114,8 @@ void HBasicBlock::AddInstruction(HInstruction* instr) {
ASSERT(!instr->IsLinked());
ASSERT(!IsFinished());
if (first_ == NULL) {
+ ASSERT(last_environment() != NULL);
+ ASSERT(!last_environment()->ast_id().IsNone());
HBlockEntry* entry = new(zone()) HBlockEntry();
entry->InitializeAsFirst(this);
first_ = last_ = entry;
@@ -231,6 +233,7 @@ void HBasicBlock::SetJoinId(BailoutId ast_id) {
predecessor->last_environment()->closure()->shared()
->VerifyBailoutId(ast_id)));
simulate->set_ast_id(ast_id);
+ predecessor->last_environment()->set_ast_id(ast_id);
}
}
@@ -619,6 +622,11 @@ HConstant* HGraph::GetConstant1() {
}
+HConstant* HGraph::GetConstant2() {
+ return GetConstantInt32(&constant_2_, 1);
Jakob Kummerow 2013/03/11 16:36:07 1 is the new 2?
danno 2013/03/13 15:36:26 Done.
+}
+
+
HConstant* HGraph::GetConstantMinus1() {
return GetConstantInt32(&constant_minus1_, -1);
}
@@ -700,7 +708,7 @@ HGraphBuilder::IfBuilder::IfBuilder(HGraphBuilder* builder, BailoutId id)
}
-HInstruction* HGraphBuilder::IfBuilder::BeginTrue(
+HInstruction* HGraphBuilder::IfBuilder::BeginIf(
HValue* left,
HValue* right,
Token::Value token,
@@ -718,7 +726,20 @@ HInstruction* HGraphBuilder::IfBuilder::BeginTrue(
}
-void HGraphBuilder::IfBuilder::BeginFalse() {
+HInstruction* HGraphBuilder::IfBuilder::BeginIfObjectsEqual(
+ HValue* left,
+ HValue* right) {
+ HCompareObjectEqAndBranch* compare =
+ new(zone()) HCompareObjectEqAndBranch(left, right);
+ compare->SetSuccessorAt(0, first_true_block_);
+ compare->SetSuccessorAt(1, first_false_block_);
+ builder_->current_block()->Finish(compare);
+ builder_->set_current_block(first_true_block_);
+ return compare;
+}
+
+
+void HGraphBuilder::IfBuilder::BeginElse() {
last_true_block_ = builder_->current_block();
ASSERT(!last_true_block_->IsFinished());
builder_->set_current_block(first_false_block_);
@@ -731,7 +752,7 @@ void HGraphBuilder::IfBuilder::End() {
HBasicBlock* last_false_block = builder_->current_block();
ASSERT(!last_false_block->IsFinished());
HEnvironment* merge_env =
- last_true_block_->last_environment()->Copy();
+ last_true_block_->last_environment()->CopyWithoutHistory();
merge_block_ = builder_->CreateBasicBlock(merge_env);
last_true_block_->Goto(merge_block_);
last_false_block->Goto(merge_block_);
@@ -853,6 +874,7 @@ void HGraphBuilder::AddSimulate(BailoutId id,
RemovableSimulate removable) {
ASSERT(current_block() != NULL);
current_block()->AddSimulate(id, removable);
+ environment()->set_ast_id(id);
}
@@ -950,7 +972,8 @@ HInstruction* HGraphBuilder::BuildFastElementAccess(
HValue* val,
HValue* load_dependency,
ElementsKind elements_kind,
- bool is_store) {
+ bool is_store,
+ KeyedAccessStoreMode store_mode) {
Zone* zone = this->zone();
if (is_store) {
ASSERT(val != NULL);
@@ -978,6 +1001,106 @@ HInstruction* HGraphBuilder::BuildFastElementAccess(
}
+HValue* HGraphBuilder::BuildCheckForCapacityGrow(HValue* object,
+ HValue* elements,
+ ElementsKind kind,
+ HValue* length,
+ HValue* key,
+ bool is_js_array) {
+ BailoutId ast_id = environment()->ast_id();
+ Zone* zone = this->zone();
+ IfBuilder length_checker_if(this, ast_id);
Jakob Kummerow 2013/03/11 16:36:07 nit: Drop the _if. Just length_checker. It's clean
danno 2013/03/13 15:36:26 Done.
+
+ length_checker_if.BeginIf(length, key, Token::EQ);
+
+ HValue* current_capacity =
+ AddInstruction(new(zone) HFixedArrayBaseLength(elements));
+
+ IfBuilder capacity_checker_if(this, ast_id);
Jakob Kummerow 2013/03/11 16:36:07 again
danno 2013/03/13 15:36:26 Done.
+
+ capacity_checker_if.BeginIf(length, current_capacity, Token::EQ);
+
+ HValue* context = environment()->LookupContext();
+
+ HValue* new_capacity =
+ BuildNewElementsCapacity(context, current_capacity);
+
+ HValue* new_elements = BuildGrowElementsCapacity(object, elements,
+ kind, length,
+ new_capacity, ast_id);
+
+ environment()->Push(new_elements);
+ capacity_checker_if.BeginElse();
+
+ environment()->Push(elements);
+ capacity_checker_if.End();
+
+ if (is_js_array) {
+ HValue* new_length = AddInstruction(
+ HAdd::New(zone, context, length, graph_->GetConstant1()));
+ new_length->ChangeRepresentation(Representation::Integer32());
+ new_length->ClearFlag(HValue::kCanOverflow);
+ AddSimulate(ast_id, REMOVABLE_SIMULATE);
+
+ Isolate* isolate = graph()->isolate();
Jakob Kummerow 2013/03/11 16:36:07 no need for this, HGraphBuilder has an isolate() a
danno 2013/03/13 15:36:26 Done.
+ Factory* factory = isolate->factory();
+ HInstruction* length_store = AddInstruction(new(zone) HStoreNamedField(
+ object,
+ factory->length_field_string(),
+ new_length, true,
+ JSArray::kLengthOffset));
+ length_store->SetGVNFlag(kChangesArrayLengths);
+ AddSimulate(ast_id, REMOVABLE_SIMULATE);
+ }
+
+ length_checker_if.BeginElse();
+
+ AddBoundsCheck(key, length, ALLOW_SMI_KEY);
+ environment()->Push(elements);
+
+ length_checker_if.End();
+
+ return environment()->Pop();
+}
+
+
+HValue* HGraphBuilder::BuildCopyElementsOnWrite(HValue* object,
+ HValue* elements,
+ ElementsKind kind,
+ HValue* length) {
+ BailoutId ast_id = environment()->ast_id();
+ Zone* zone = this->zone();
+ Heap* heap = info_->isolate()->heap();
Jakob Kummerow 2013/03/11 16:36:07 s/info_->// (or s/info_/this/ if you like needless
danno 2013/03/13 15:36:26 Done.
+ HValue* elements_map =
+ AddInstruction(new(zone) HLoadNamedField(elements, true,
Jakob Kummerow 2013/03/11 16:36:07 Are you intentionally not using an HCompareMap ins
danno 2013/03/13 15:36:26 Done.
+ JSObject::kMapOffset));
+ Handle<Map> map(Handle<Map>(heap->fixed_cow_array_map()));
+ HValue* cow_map =
+ AddInstruction(new(zone) HConstant(map, Representation::Tagged()));
+
+ IfBuilder cow_checker(this, ast_id);
+
+ cow_checker.BeginIfObjectsEqual(elements_map, cow_map);
+
+ HValue* capacity =
+ AddInstruction(new(zone) HFixedArrayBaseLength(elements));
+
+ HValue* new_elements = BuildGrowElementsCapacity(object, elements,
+ kind, length,
+ capacity, ast_id);
+
+ environment()->Push(new_elements);
+
+ cow_checker.BeginElse();
+
+ environment()->Push(elements);
+
+ cow_checker.End();
+
+ return environment()->Pop();
+}
+
+
HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
HValue* object,
HValue* key,
@@ -986,7 +1109,9 @@ HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
bool is_js_array,
ElementsKind elements_kind,
bool is_store,
+ KeyedAccessStoreMode store_mode,
Representation checked_index_representation) {
+ ASSERT(!IsExternalArrayElementsKind(elements_kind) || !is_js_array);
Zone* zone = this->zone();
// No GVNFlag is necessary for ElementsKind if there is an explicit dependency
// on a HElementsTransition instruction. The flag can also be removed if the
@@ -1002,46 +1127,104 @@ HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
}
bool fast_smi_only_elements = IsFastSmiElementsKind(elements_kind);
bool fast_elements = IsFastObjectElementsKind(elements_kind);
- HInstruction* elements =
+ HValue* elements =
AddInstruction(new(zone) HLoadElements(object, mapcheck));
- if (is_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 = new(zone) HCheckMaps(
elements, isolate()->factory()->fixed_array_map(), zone);
check_cow_map->ClearGVNFlag(kDependsOnElementsKind);
AddInstruction(check_cow_map);
}
HInstruction* length = NULL;
- HInstruction* checked_key = NULL;
- if (IsExternalArrayElementsKind(elements_kind)) {
+ if (is_js_array) {
+ length = AddInstruction(new(zone) HJSArrayLength(object, mapcheck,
+ HType::Smi()));
+ } else {
length = AddInstruction(new(zone) HFixedArrayBaseLength(elements));
- checked_key = AddBoundsCheck(
- key, length, ALLOW_SMI_KEY, checked_index_representation);
- HLoadExternalArrayPointer* external_elements =
- new(zone) HLoadExternalArrayPointer(elements);
- AddInstruction(external_elements);
- return BuildExternalArrayElementAccess(
- external_elements, checked_key, val, mapcheck,
- elements_kind, is_store);
+ }
+ HValue* checked_key = NULL;
+ if (IsExternalArrayElementsKind(elements_kind)) {
+ if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) {
+ HLoadExternalArrayPointer* external_elements =
+ new(zone) HLoadExternalArrayPointer(elements);
+ AddInstruction(external_elements);
+ HCheckSmiOrInt32* checked_index =
+ new(graph()->zone()) HCheckSmiOrInt32(key);
+ AddInstruction(checked_index);
+ BailoutId previous_id = environment()->ast_id();
+ ASSERT(!previous_id.IsNone());
+ IfBuilder oob_ignore_check(this, previous_id);
Jakob Kummerow 2013/03/11 16:36:07 How about we call this IfBuilder length_checker (a
danno 2013/03/13 15:36:26 Done.
+ oob_ignore_check.BeginIf(checked_index, length, Token::LT);
+ IfBuilder oob_ignore_check2(this, previous_id);
Jakob Kummerow 2013/03/11 16:36:07 ...and this one negative_checker?
danno 2013/03/13 15:36:26 Done.
+ HInstruction* bounds_check =
+ oob_ignore_check2.BeginIf(checked_index,
+ graph()->GetConstant0(),
+ Token::LT);
+ // Negative array indices can't be ignored and must be handled by the
+ // runtime.
+ AddSoftDeoptimize();
Jakob Kummerow 2013/03/11 16:36:07 You don't want a soft deopt here. HSoftDeoptimize
danno 2013/03/13 15:36:26 Done.
+ oob_ignore_check2.BeginElse();
+ HInstruction* result = BuildExternalArrayElementAccess(
+ external_elements, key, val, bounds_check,
+ elements_kind, is_store);
+ AddInstruction(result);
+ oob_ignore_check2.End();
+ oob_ignore_check.BeginElse();
+ oob_ignore_check.End();
+ return result;
+ } else {
+ ASSERT(store_mode == STANDARD_STORE);
+ checked_key = AddBoundsCheck(
+ key, length, ALLOW_SMI_KEY, checked_index_representation);
+ HLoadExternalArrayPointer* external_elements =
+ new(zone) HLoadExternalArrayPointer(elements);
+ AddInstruction(external_elements);
+ return AddInstruction(BuildExternalArrayElementAccess(
+ external_elements, checked_key, val, mapcheck,
+ elements_kind, is_store));
+ }
}
ASSERT(fast_smi_only_elements ||
fast_elements ||
IsFastDoubleElementsKind(elements_kind));
- if (is_js_array) {
- length = AddInstruction(new(zone) HJSArrayLength(object, mapcheck,
- HType::Smi()));
+
+ if (is_store && IsFastSmiElementsKind(elements_kind) &&
+ val->type().IsTagged() && !val->type().IsSmi()) {
Jakob Kummerow 2013/03/11 16:36:07 Fun fact: there is no HType (except "uninitialized
danno 2013/03/13 15:36:26 Done.
+ AddInstruction(new(zone) HCheckSmi(val));
+ }
+
+ if (IsGrowStoreMode(store_mode)) {
+ elements = BuildCheckForCapacityGrow(object, elements, elements_kind,
+ length, key, is_js_array);
+ checked_key = key;
} else {
- length = AddInstruction(new(zone) HFixedArrayBaseLength(elements));
+ checked_key = AddBoundsCheck(
+ key, length, ALLOW_SMI_KEY, checked_index_representation);
+
+ if (is_store && (fast_elements || fast_smi_only_elements)) {
+ if (store_mode == STORE_NO_TRANSITION_HANDLE_COW) {
+ elements =
+ BuildCopyElementsOnWrite(object, elements, elements_kind,
+ length);
Jakob Kummerow 2013/03/11 16:36:07 nit: fits on the previous line
danno 2013/03/13 15:36:26 Done.
+ } else {
+ HCheckMaps* check_cow_map = new(zone) HCheckMaps(
+ elements, Isolate::Current()->factory()->fixed_array_map(), zone);
Jakob Kummerow 2013/03/11 16:36:07 s/Isolate::Current()/isolate()/
danno 2013/03/13 15:36:26 Done.
+ check_cow_map->ClearGVNFlag(kDependsOnElementsKind);
+ AddInstruction(check_cow_map);
+ }
+ }
}
- checked_key = AddBoundsCheck(
- key, length, ALLOW_SMI_KEY, checked_index_representation);
- return BuildFastElementAccess(elements, checked_key, val, mapcheck,
- elements_kind, is_store);
+ return AddInstruction(
+ BuildFastElementAccess(elements, checked_key, val, mapcheck,
+ elements_kind, is_store, store_mode));
}
-HValue* HGraphBuilder::BuildAllocateElements(HContext* context,
+HValue* HGraphBuilder::BuildAllocateElements(HValue* context,
ElementsKind kind,
- HValue* capacity) {
+ HValue* capacity,
+ BailoutId ast_id) {
Zone* zone = this->zone();
int elements_size = IsFastDoubleElementsKind(kind)
@@ -1076,14 +1259,14 @@ HValue* HGraphBuilder::BuildAllocateElements(HContext* context,
Handle<Map> map = IsFastDoubleElementsKind(kind)
? factory->fixed_double_array_map()
: factory->fixed_array_map();
- BuildStoreMap(elements, map, BailoutId::StubEntry());
+ BuildStoreMap(elements, map, ast_id);
Handle<String> fixed_array_length_field_name = factory->length_field_string();
HInstruction* store_length =
new(zone) HStoreNamedField(elements, fixed_array_length_field_name,
capacity, true, FixedArray::kLengthOffset);
AddInstruction(store_length);
- AddSimulate(BailoutId::StubEntry(), FIXED_SIMULATE);
+ AddSimulate(ast_id, REMOVABLE_SIMULATE);
return elements;
}
@@ -1100,7 +1283,7 @@ HInstruction* HGraphBuilder::BuildStoreMap(HValue* object,
true, JSObject::kMapOffset);
store_map->SetGVNFlag(kChangesMaps);
AddInstruction(store_map);
- AddSimulate(id, FIXED_SIMULATE);
+ AddSimulate(id, REMOVABLE_SIMULATE);
return store_map;
}
@@ -1115,17 +1298,135 @@ HInstruction* HGraphBuilder::BuildStoreMap(HValue* object,
}
-void HGraphBuilder::BuildCopyElements(HContext* context,
+HValue* HGraphBuilder::BuildNewElementsCapacity(HValue* context,
+ HValue* old_capacity) {
+ Zone* zone = this->zone();
+ HValue* half_old_capacity =
+ AddInstruction(HDiv::New(zone,
Jakob Kummerow 2013/03/11 16:36:07 prefer HSar (then you won't need GetConstant2() at
danno 2013/03/13 15:36:26 Done.
+ context,
+ old_capacity,
+ graph_->GetConstant2()));
+ half_old_capacity->ChangeRepresentation(Representation::Integer32());
+ half_old_capacity->ClearFlag(HValue::kCanOverflow);
+
+ HValue* new_capacity = AddInstruction(
+ HAdd::New(zone, context, half_old_capacity, old_capacity));
+ new_capacity->ChangeRepresentation(Representation::Integer32());
+ new_capacity->ClearFlag(HValue::kCanOverflow);
+
+ HValue* min_growth =
+ AddInstruction(new(zone) HConstant(4, Representation::Integer32()));
Jakob Kummerow 2013/03/11 16:36:07 The C++ version (NewElementsCapacity in objects.h)
danno 2013/03/13 15:36:26 Done.
+
+ new_capacity = AddInstruction(
+ HAdd::New(zone, context, new_capacity, min_growth));
+ new_capacity->ChangeRepresentation(Representation::Integer32());
+ new_capacity->ClearFlag(HValue::kCanOverflow);
+
+ return new_capacity;
+}
+
+
+void HGraphBuilder::BuildNewSpaceArrayCheck(HValue* length, ElementsKind kind) {
+ Zone* zone = this->zone();
+ Heap* heap = info_->isolate()->heap();
Jakob Kummerow 2013/03/11 16:36:07 s/info_->//
danno 2013/03/13 15:36:26 Done.
+ int element_size = IsFastDoubleElementsKind(kind)
+ ? kDoubleSize
Jakob Kummerow 2013/03/11 16:36:07 nit: fits on previous line. For your copy/paste co
danno 2013/03/13 15:36:26 Done.
+ : kPointerSize;
+ int max_size = heap->MaxNewSpaceAllocationSize() / element_size;
+ max_size -= sizeof(JSArray) / element_size;
Jakob Kummerow 2013/03/11 16:36:07 I think you mean s/sizeof(JSArray)/JSArray::kSize/
danno 2013/03/13 15:36:26 Done.
+ HConstant* max_size_constant =
+ new(zone) HConstant(max_size, Representation::Integer32());
+ AddInstruction(max_size_constant);
+ // Since we're forcing Integer32 representation for this HBoundsCheck,
Jakob Kummerow 2013/03/11 16:36:07 I'd prefer to make this explicit by passing (_, _,
danno 2013/03/13 15:36:26 Done.
+ // there's no need to Smi-check the index.
+ AddInstruction(new(zone) HBoundsCheck(length, max_size_constant));
+}
+
+
+HValue* HGraphBuilder::BuildGrowElementsCapacity(HValue* object,
+ HValue* elements,
+ ElementsKind kind,
+ HValue* length,
+ HValue* new_capacity,
+ BailoutId ast_id) {
+ Zone* zone = this->zone();
+ HValue* context = environment()->LookupContext();
+
+ BuildNewSpaceArrayCheck(new_capacity, kind);
+
+ HValue* new_elements =
+ BuildAllocateElements(context, kind, new_capacity, ast_id);
+
+ BuildCopyElements(context, elements, kind,
+ new_elements, kind,
+ length, new_capacity, ast_id);
+
+ Isolate* isolate = graph()->isolate();
Jakob Kummerow 2013/03/11 16:36:07 no need for this, just use [this->]isolate() direc
danno 2013/03/13 15:36:26 Done.
+ Factory* factory = isolate->factory();
+ HInstruction* elements_store = AddInstruction(new(zone) HStoreNamedField(
+ object,
+ factory->elements_field_string(),
+ new_elements, true,
+ JSArray::kElementsOffset));
+ elements_store->SetGVNFlag(kChangesElementsPointer);
+
+ return new_elements;
+}
+
+
+void HGraphBuilder::BuildFillElementsWithHole(HValue* context,
+ HValue* elements,
+ ElementsKind elements_kind,
+ HValue* from,
+ HValue* to,
+ BailoutId ast_id) {
+ // Fast elements kinds need to be initialized in case statements below cause
+ // a garbage collection.
+ Factory* factory = info_->isolate()->factory();
Jakob Kummerow 2013/03/11 16:36:07 s/info_->//
danno 2013/03/13 15:36:26 Done.
+
+ double nan_double = FixedDoubleArray::hole_nan_as_double();
+ Zone* zone = this->zone();
+ HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind)
+ ? AddInstruction(new(zone) HConstant(factory->the_hole_value(),
+ Representation::Tagged()))
+ : AddInstruction(new(zone) HConstant(nan_double,
+ Representation::Double()));
+
+ LoopBuilder builder(this, context, LoopBuilder::kPostIncrement, ast_id);
+
+ HValue* key = builder.BeginBody(from, to, Token::LT);
+
+ AddInstruction(new(zone) HStoreKeyed(elements, key, hole,
+ elements_kind));
Jakob Kummerow 2013/03/11 16:36:07 nit: fits on previous line
danno 2013/03/13 15:36:26 Done.
+ AddSimulate(ast_id, REMOVABLE_SIMULATE);
+
+ builder.EndBody();
+}
+
+
+void HGraphBuilder::BuildCopyElements(HValue* context,
HValue* from_elements,
ElementsKind from_elements_kind,
HValue* to_elements,
ElementsKind to_elements_kind,
- HValue* length) {
- LoopBuilder builder(this, context, LoopBuilder::kPostIncrement,
- BailoutId::StubEntry());
+ HValue* length,
+ HValue* capacity,
+ BailoutId ast_id) {
+ bool pre_fill_with_holes =
+ IsFastDoubleElementsKind(from_elements_kind) &&
+ IsFastObjectElementsKind(to_elements_kind);
- HValue* key = builder.BeginBody(graph()->GetConstant0(),
- length, Token::LT);
+ if (pre_fill_with_holes) {
+ // If the copy might trigger a GC, make sure that the FixedArray is
+ // pre-initialized with holes to make sure that it's always in a consistent
+ // state.
+ BuildFillElementsWithHole(context, to_elements, to_elements_kind,
+ graph()->GetConstant0(), capacity, ast_id);
+ }
+
+ LoopBuilder builder(this, context, LoopBuilder::kPostIncrement, ast_id);
+
+ HValue* key = builder.BeginBody(graph()->GetConstant0(), length, Token::LT);
HValue* element =
AddInstruction(new(zone()) HLoadKeyed(from_elements, key, NULL,
@@ -1134,9 +1435,24 @@ void HGraphBuilder::BuildCopyElements(HContext* context,
AddInstruction(new(zone()) HStoreKeyed(to_elements, key, element,
to_elements_kind));
- AddSimulate(BailoutId::StubEntry(), REMOVABLE_SIMULATE);
+ AddSimulate(ast_id, REMOVABLE_SIMULATE);
builder.EndBody();
+
+ if (!pre_fill_with_holes && length != capacity) {
+ // Fill unused capacity with the hole.
+ BuildFillElementsWithHole(context, to_elements, to_elements_kind,
+ key, capacity, ast_id);
+ }
+}
+
+
+void HGraphBuilder::AddSoftDeoptimize() {
+ if (FLAG_always_opt) return;
+ if (current_block()->IsDeoptimizing()) return;
+ AddInstruction(new(zone()) HSoftDeoptimize());
+ current_block()->MarkAsDeoptimizing();
+ graph()->set_has_soft_deoptimize(true);
}
@@ -4499,15 +4815,6 @@ void HOptimizedGraphBuilder::PushAndAdd(HInstruction* instr) {
}
-void HOptimizedGraphBuilder::AddSoftDeoptimize() {
- if (FLAG_always_opt) return;
- if (current_block()->IsDeoptimizing()) return;
- AddInstruction(new(zone()) HSoftDeoptimize());
- current_block()->MarkAsDeoptimizing();
- graph()->set_has_soft_deoptimize(true);
-}
-
-
template <class Instruction>
HInstruction* HOptimizedGraphBuilder::PreProcessCall(Instruction* call) {
int count = call->argument_count();
@@ -6781,7 +7088,8 @@ HInstruction* HOptimizedGraphBuilder::BuildMonomorphicElementAccess(
HValue* val,
HValue* dependency,
Handle<Map> map,
- bool is_store) {
+ bool is_store,
+ KeyedAccessStoreMode store_mode) {
HCheckMaps* mapcheck = new(zone()) HCheckMaps(object, map,
zone(), dependency);
AddInstruction(mapcheck);
@@ -6791,7 +7099,7 @@ HInstruction* HOptimizedGraphBuilder::BuildMonomorphicElementAccess(
return BuildUncheckedMonomorphicElementAccess(
object, key, val,
mapcheck, map->instance_type() == JS_ARRAY_TYPE,
- map->elements_kind(), is_store);
+ map->elements_kind(), is_store, store_mode);
}
@@ -6846,7 +7154,7 @@ HInstruction* HOptimizedGraphBuilder::TryBuildConsolidatedElementLoad(
object, key, val, check_maps,
most_general_consolidated_map->instance_type() == JS_ARRAY_TYPE,
most_general_consolidated_map->elements_kind(),
- false);
+ false, STANDARD_STORE);
return instr;
}
@@ -6859,6 +7167,7 @@ HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess(
BailoutId ast_id,
int position,
bool is_store,
+ KeyedAccessStoreMode store_mode,
bool* has_side_effects) {
*has_side_effects = false;
AddInstruction(new(zone()) HCheckNonSmi(object));
@@ -6869,7 +7178,6 @@ HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess(
HInstruction* consolidated_load =
TryBuildConsolidatedElementLoad(object, key, val, maps);
if (consolidated_load != NULL) {
- AddInstruction(consolidated_load);
*has_side_effects |= consolidated_load->HasObservableSideEffects();
if (position != RelocInfo::kNoPosition) {
consolidated_load->set_position(position);
@@ -6936,8 +7244,9 @@ HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess(
instr = AddInstruction(is_store ? BuildStoreKeyedGeneric(object, key, val)
: BuildLoadKeyedGeneric(object, key));
} else {
- instr = AddInstruction(BuildMonomorphicElementAccess(
- object, key, val, transition, untransitionable_map, is_store));
+ instr = BuildMonomorphicElementAccess(
+ object, key, val, transition, untransitionable_map, is_store,
+ store_mode);
}
*has_side_effects |= instr->HasObservableSideEffects();
if (position != RelocInfo::kNoPosition) instr->set_position(position);
@@ -7018,7 +7327,7 @@ HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess(
checked_key = AddBoundsCheck(key, length, ALLOW_SMI_KEY);
access = AddInstruction(BuildFastElementAccess(
elements, checked_key, val, elements_kind_branch,
- elements_kind, is_store));
+ elements_kind, is_store, STANDARD_STORE));
if (!is_store) {
Push(access);
}
@@ -7034,7 +7343,7 @@ HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess(
checked_key = AddBoundsCheck(key, length, ALLOW_SMI_KEY);
access = AddInstruction(BuildFastElementAccess(
elements, checked_key, val, elements_kind_branch,
- elements_kind, is_store));
+ elements_kind, is_store, STANDARD_STORE));
} else if (elements_kind == DICTIONARY_ELEMENTS) {
if (is_store) {
access = AddInstruction(BuildStoreKeyedGeneric(object, key, val));
@@ -7080,23 +7389,27 @@ HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess(
if (map->has_slow_elements_kind()) {
instr = is_store ? BuildStoreKeyedGeneric(obj, key, val)
: BuildLoadKeyedGeneric(obj, key);
+ AddInstruction(instr);
} else {
AddInstruction(new(zone()) HCheckNonSmi(obj));
- instr = BuildMonomorphicElementAccess(obj, key, val, NULL, map, is_store);
+ instr = BuildMonomorphicElementAccess(
+ obj, key, val, NULL, map,
+ is_store, expr->GetStoreMode());
Jakob Kummerow 2013/03/11 16:36:07 nit: fits on previous line
danno 2013/03/13 15:36:26 Done.
}
} else if (expr->GetReceiverTypes() != NULL &&
!expr->GetReceiverTypes()->is_empty()) {
return HandlePolymorphicElementAccess(
- obj, key, val, expr, ast_id, position, is_store, has_side_effects);
+ obj, key, val, expr, ast_id, position, is_store,
+ expr->GetStoreMode(), has_side_effects);
} else {
if (is_store) {
instr = BuildStoreKeyedGeneric(obj, key, val);
} else {
instr = BuildLoadKeyedGeneric(obj, key);
}
+ AddInstruction(instr);
}
if (position != RelocInfo::kNoPosition) instr->set_position(position);
- AddInstruction(instr);
*has_side_effects = instr->HasObservableSideEffects();
return instr;
}

Powered by Google App Engine
This is Rietveld 408576698