| Index: src/hydrogen.cc
|
| diff --git a/src/hydrogen.cc b/src/hydrogen.cc
|
| index f538c21c1a0394db91239756699cc490eaf7bcd1..05d4764e83f646af313c19a3a0cf99bfb5bdfeef 100644
|
| --- a/src/hydrogen.cc
|
| +++ b/src/hydrogen.cc
|
| @@ -1304,13 +1304,14 @@ HValue* HGraphBuilder::BuildWrapReceiver(HValue* object, HValue* function) {
|
| }
|
|
|
|
|
| -HValue* HGraphBuilder::BuildCheckForCapacityGrow(HValue* object,
|
| - HValue* elements,
|
| - ElementsKind kind,
|
| - HValue* length,
|
| - HValue* key,
|
| - bool is_js_array,
|
| - bool is_store) {
|
| +HValue* HGraphBuilder::BuildCheckForCapacityGrow(
|
| + HValue* object,
|
| + HValue* elements,
|
| + ElementsKind kind,
|
| + HValue* length,
|
| + HValue* key,
|
| + bool is_js_array,
|
| + PropertyAccessType access_type) {
|
| IfBuilder length_checker(this);
|
|
|
| Token::Value token = IsHoleyElementsKind(kind) ? Token::GTE : Token::EQ;
|
| @@ -1353,7 +1354,7 @@ HValue* HGraphBuilder::BuildCheckForCapacityGrow(HValue* object,
|
| new_length);
|
| }
|
|
|
| - if (is_store && kind == FAST_SMI_ELEMENTS) {
|
| + if (access_type == STORE && kind == FAST_SMI_ELEMENTS) {
|
| HValue* checked_elements = environment()->Top();
|
|
|
| // Write zero to ensure that the new element is initialized with some smi.
|
| @@ -2159,7 +2160,7 @@ HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
|
| HValue* val,
|
| bool is_js_array,
|
| ElementsKind elements_kind,
|
| - bool is_store,
|
| + PropertyAccessType access_type,
|
| LoadKeyedHoleMode load_mode,
|
| KeyedAccessStoreMode store_mode) {
|
| ASSERT((!IsExternalArrayElementsKind(elements_kind) &&
|
| @@ -2172,14 +2173,14 @@ 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 && is_store)) {
|
| + (elements_kind == FAST_ELEMENTS && access_type == 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 (is_store && (fast_elements || fast_smi_only_elements) &&
|
| + if (access_type == 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());
|
| @@ -2215,7 +2216,7 @@ HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
|
| key, graph()->GetConstant0(), Token::GTE);
|
| negative_checker.Then();
|
| HInstruction* result = AddElementAccess(
|
| - backing_store, key, val, bounds_check, elements_kind, is_store);
|
| + backing_store, key, val, bounds_check, elements_kind, access_type);
|
| negative_checker.ElseDeopt("Negative key encountered");
|
| negative_checker.End();
|
| length_checker.End();
|
| @@ -2225,7 +2226,7 @@ HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
|
| checked_key = Add<HBoundsCheck>(key, length);
|
| return AddElementAccess(
|
| backing_store, checked_key, val,
|
| - checked_object, elements_kind, is_store);
|
| + checked_object, elements_kind, access_type);
|
| }
|
| }
|
| ASSERT(fast_smi_only_elements ||
|
| @@ -2235,7 +2236,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 (is_store && IsFastSmiElementsKind(elements_kind) &&
|
| + if (access_type == STORE && IsFastSmiElementsKind(elements_kind) &&
|
| !val->type().IsSmi()) {
|
| val = AddUncasted<HForceRepresentation>(val, Representation::Smi());
|
| }
|
| @@ -2244,12 +2245,12 @@ HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
|
| NoObservableSideEffectsScope no_effects(this);
|
| elements = BuildCheckForCapacityGrow(checked_object, elements,
|
| elements_kind, length, key,
|
| - is_js_array, is_store);
|
| + is_js_array, access_type);
|
| checked_key = key;
|
| } else {
|
| checked_key = Add<HBoundsCheck>(key, length);
|
|
|
| - if (is_store && (fast_elements || fast_smi_only_elements)) {
|
| + if (access_type == STORE && (fast_elements || fast_smi_only_elements)) {
|
| if (store_mode == STORE_NO_TRANSITION_HANDLE_COW) {
|
| NoObservableSideEffectsScope no_effects(this);
|
| elements = BuildCopyElementsOnWrite(checked_object, elements,
|
| @@ -2262,7 +2263,7 @@ HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
|
| }
|
| }
|
| return AddElementAccess(elements, checked_key, val, checked_object,
|
| - elements_kind, is_store, load_mode);
|
| + elements_kind, access_type, load_mode);
|
| }
|
|
|
|
|
| @@ -2404,9 +2405,9 @@ HInstruction* HGraphBuilder::AddElementAccess(
|
| HValue* val,
|
| HValue* dependency,
|
| ElementsKind elements_kind,
|
| - bool is_store,
|
| + PropertyAccessType access_type,
|
| LoadKeyedHoleMode load_mode) {
|
| - if (is_store) {
|
| + if (access_type == STORE) {
|
| ASSERT(val != NULL);
|
| if (elements_kind == EXTERNAL_UINT8_CLAMPED_ELEMENTS ||
|
| elements_kind == UINT8_CLAMPED_ELEMENTS) {
|
| @@ -2418,7 +2419,7 @@ HInstruction* HGraphBuilder::AddElementAccess(
|
| : INITIALIZING_STORE);
|
| }
|
|
|
| - ASSERT(!is_store);
|
| + ASSERT(access_type == LOAD);
|
| ASSERT(val == NULL);
|
| HLoadKeyed* load = Add<HLoadKeyed>(
|
| elements, checked_key, dependency, elements_kind, load_mode);
|
| @@ -4782,14 +4783,14 @@ void HOptimizedGraphBuilder::VisitConditional(Conditional* expr) {
|
|
|
| HOptimizedGraphBuilder::GlobalPropertyAccess
|
| HOptimizedGraphBuilder::LookupGlobalProperty(
|
| - Variable* var, LookupResult* lookup, bool is_store) {
|
| + Variable* var, LookupResult* lookup, PropertyAccessType access_type) {
|
| 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() ||
|
| - (is_store && lookup->IsReadOnly()) ||
|
| + (access_type == STORE && lookup->IsReadOnly()) ||
|
| lookup->holder() != *global) {
|
| return kUseGeneric;
|
| }
|
| @@ -4835,8 +4836,7 @@ void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
|
| }
|
|
|
| LookupResult lookup(isolate());
|
| - GlobalPropertyAccess type =
|
| - LookupGlobalProperty(variable, &lookup, false);
|
| + GlobalPropertyAccess type = LookupGlobalProperty(variable, &lookup, LOAD);
|
|
|
| if (type == kUseCell &&
|
| current_info()->global_object()->IsAccessCheckNeeded()) {
|
| @@ -5751,8 +5751,7 @@ void HOptimizedGraphBuilder::BuildStore(Expression* expr,
|
| HValue* object = environment()->ExpressionStackAt(2);
|
| bool has_side_effects = false;
|
| HandleKeyedElementAccess(object, key, value, expr,
|
| - true, // is_store
|
| - &has_side_effects);
|
| + STORE, &has_side_effects);
|
| Drop(3);
|
| Push(value);
|
| Add<HSimulate>(return_id, REMOVABLE_SIMULATE);
|
| @@ -5802,7 +5801,7 @@ void HOptimizedGraphBuilder::HandleGlobalVariableAssignment(
|
| HValue* value,
|
| BailoutId ast_id) {
|
| LookupResult lookup(isolate());
|
| - GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true);
|
| + GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, STORE);
|
| if (type == kUseCell) {
|
| Handle<GlobalObject> global(current_info()->global_object());
|
| Handle<PropertyCell> cell(global->GetPropertyCell(&lookup));
|
| @@ -6196,7 +6195,7 @@ HInstruction* HOptimizedGraphBuilder::BuildMonomorphicElementAccess(
|
| HValue* val,
|
| HValue* dependency,
|
| Handle<Map> map,
|
| - bool is_store,
|
| + PropertyAccessType access_type,
|
| KeyedAccessStoreMode store_mode) {
|
| HCheckMaps* checked_object = Add<HCheckMaps>(object, map, top_info(),
|
| dependency);
|
| @@ -6204,7 +6203,7 @@ HInstruction* HOptimizedGraphBuilder::BuildMonomorphicElementAccess(
|
| checked_object->ClearGVNFlag(kDependsOnElementsKind);
|
| }
|
|
|
| - if (is_store && map->prototype()->IsJSObject()) {
|
| + if (access_type == 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.
|
| @@ -6223,7 +6222,7 @@ HInstruction* HOptimizedGraphBuilder::BuildMonomorphicElementAccess(
|
| return BuildUncheckedMonomorphicElementAccess(
|
| checked_object, key, val,
|
| map->instance_type() == JS_ARRAY_TYPE,
|
| - map->elements_kind(), is_store,
|
| + map->elements_kind(), access_type,
|
| load_mode, store_mode);
|
| }
|
|
|
| @@ -6289,7 +6288,7 @@ HInstruction* HOptimizedGraphBuilder::TryBuildConsolidatedElementLoad(
|
| checked_object, key, val,
|
| most_general_consolidated_map->instance_type() == JS_ARRAY_TYPE,
|
| consolidated_elements_kind,
|
| - false, NEVER_RETURN_HOLE, STANDARD_STORE);
|
| + LOAD, NEVER_RETURN_HOLE, STANDARD_STORE);
|
| return instr;
|
| }
|
|
|
| @@ -6299,13 +6298,13 @@ HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess(
|
| HValue* key,
|
| HValue* val,
|
| SmallMapList* maps,
|
| - bool is_store,
|
| + PropertyAccessType access_type,
|
| KeyedAccessStoreMode store_mode,
|
| bool* has_side_effects) {
|
| *has_side_effects = false;
|
| BuildCheckHeapObject(object);
|
|
|
| - if (!is_store) {
|
| + if (access_type == LOAD) {
|
| HInstruction* consolidated_load =
|
| TryBuildConsolidatedElementLoad(object, key, val, maps);
|
| if (consolidated_load != NULL) {
|
| @@ -6358,15 +6357,16 @@ HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess(
|
| HInstruction* instr = NULL;
|
| if (untransitionable_map->has_slow_elements_kind() ||
|
| !untransitionable_map->IsJSObjectMap()) {
|
| - instr = AddInstruction(is_store ? BuildStoreKeyedGeneric(object, key, val)
|
| - : BuildLoadKeyedGeneric(object, key));
|
| + instr = AddInstruction(access_type == STORE
|
| + ? BuildStoreKeyedGeneric(object, key, val)
|
| + : BuildLoadKeyedGeneric(object, key));
|
| } else {
|
| instr = BuildMonomorphicElementAccess(
|
| - object, key, val, transition, untransitionable_map, is_store,
|
| + object, key, val, transition, untransitionable_map, access_type,
|
| store_mode);
|
| }
|
| *has_side_effects |= instr->HasObservableSideEffects();
|
| - return is_store ? NULL : instr;
|
| + return access_type == STORE ? NULL : instr;
|
| }
|
|
|
| HBasicBlock* join = graph()->CreateBasicBlock();
|
| @@ -6384,7 +6384,7 @@ HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess(
|
| set_current_block(this_map);
|
| HInstruction* access = NULL;
|
| if (IsDictionaryElementsKind(elements_kind)) {
|
| - access = is_store
|
| + access = access_type == STORE
|
| ? AddInstruction(BuildStoreKeyedGeneric(object, key, val))
|
| : AddInstruction(BuildLoadKeyedGeneric(object, key));
|
| } else {
|
| @@ -6395,14 +6395,14 @@ HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess(
|
| access = BuildUncheckedMonomorphicElementAccess(
|
| mapcompare, key, val,
|
| map->instance_type() == JS_ARRAY_TYPE,
|
| - elements_kind, is_store,
|
| + elements_kind, access_type,
|
| 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 (!is_store) {
|
| + if (access_type == LOAD) {
|
| Push(access);
|
| }
|
| NoObservableSideEffectsScope scope(this);
|
| @@ -6415,7 +6415,7 @@ HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess(
|
| FinishExitWithHardDeoptimization("Unknown map in polymorphic element access",
|
| join);
|
| set_current_block(join);
|
| - return is_store ? NULL : Pop();
|
| + return access_type == STORE ? NULL : Pop();
|
| }
|
|
|
|
|
| @@ -6424,7 +6424,7 @@ HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess(
|
| HValue* key,
|
| HValue* val,
|
| Expression* expr,
|
| - bool is_store,
|
| + PropertyAccessType access_type,
|
| bool* has_side_effects) {
|
| ASSERT(!expr->IsPropertyName());
|
| HInstruction* instr = NULL;
|
| @@ -6433,7 +6433,8 @@ HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess(
|
| bool monomorphic = ComputeReceiverTypes(expr, obj, &types, zone());
|
|
|
| bool force_generic = false;
|
| - if (is_store && (monomorphic || (types != NULL && !types->is_empty()))) {
|
| + if (access_type == 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
|
| @@ -6451,20 +6452,21 @@ HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess(
|
| if (monomorphic) {
|
| Handle<Map> map = types->first();
|
| if (map->has_slow_elements_kind() || !map->IsJSObjectMap()) {
|
| - instr = is_store ? BuildStoreKeyedGeneric(obj, key, val)
|
| - : BuildLoadKeyedGeneric(obj, key);
|
| + instr = access_type == STORE
|
| + ? BuildStoreKeyedGeneric(obj, key, val)
|
| + : BuildLoadKeyedGeneric(obj, key);
|
| AddInstruction(instr);
|
| } else {
|
| BuildCheckHeapObject(obj);
|
| instr = BuildMonomorphicElementAccess(
|
| - obj, key, val, NULL, map, is_store, expr->GetStoreMode());
|
| + obj, key, val, NULL, map, access_type, expr->GetStoreMode());
|
| }
|
| } else if (!force_generic && (types != NULL && !types->is_empty())) {
|
| return HandlePolymorphicElementAccess(
|
| - obj, key, val, types, is_store,
|
| + obj, key, val, types, access_type,
|
| expr->GetStoreMode(), has_side_effects);
|
| } else {
|
| - if (is_store) {
|
| + if (access_type == STORE) {
|
| if (expr->IsAssignment() &&
|
| expr->AsAssignment()->HasNoTypeInformation()) {
|
| Add<HDeoptimize>("Insufficient type feedback for keyed store",
|
| @@ -6653,9 +6655,7 @@ void HOptimizedGraphBuilder::BuildLoad(Property* expr,
|
|
|
| bool has_side_effects = false;
|
| HValue* load = HandleKeyedElementAccess(
|
| - obj, key, NULL, expr,
|
| - false, // is_store
|
| - &has_side_effects);
|
| + obj, key, NULL, expr, LOAD, &has_side_effects);
|
| if (has_side_effects) {
|
| if (ast_context()->IsEffect()) {
|
| Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
|
| @@ -7584,7 +7584,7 @@ bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall(
|
| }
|
| reduced_length = AddUncasted<HSub>(length, graph()->GetConstant1());
|
| result = AddElementAccess(elements, reduced_length, NULL,
|
| - bounds_check, elements_kind, false);
|
| + bounds_check, elements_kind, LOAD);
|
| Factory* factory = isolate()->factory();
|
| double nan_double = FixedDoubleArray::hole_nan_as_double();
|
| HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind)
|
| @@ -7594,7 +7594,7 @@ bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall(
|
| elements_kind = FAST_HOLEY_ELEMENTS;
|
| }
|
| AddElementAccess(
|
| - elements, reduced_length, hole, bounds_check, elements_kind, true);
|
| + elements, reduced_length, hole, bounds_check, elements_kind, STORE);
|
| Add<HStoreNamedField>(
|
| checked_object, HObjectAccess::ForArrayLength(elements_kind),
|
| reduced_length, STORE_TO_INITIALIZED_ENTRY);
|
| @@ -8010,7 +8010,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, false);
|
| + GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, LOAD);
|
| if (type == kUseCell &&
|
| !current_info()->global_object()->IsAccessCheckNeeded()) {
|
| Handle<GlobalObject> global(current_info()->global_object());
|
|
|