| Index: src/hydrogen.cc
|
| diff --git a/src/hydrogen.cc b/src/hydrogen.cc
|
| index 4cd0ff0f08658ad651ac99c4552b9d1100a380a3..c82ce6405813c035602b4d599ad55a165e2dd5d2 100644
|
| --- a/src/hydrogen.cc
|
| +++ b/src/hydrogen.cc
|
| @@ -1191,7 +1191,7 @@ void HGraphBuilder::BuildTransitionElementsKind(HValue* object,
|
| }
|
|
|
| if (!IsSimpleMapChangeTransition(from_kind, to_kind)) {
|
| - HInstruction* elements = AddLoadElements(object, NULL);
|
| + HInstruction* elements = AddLoadElements(object);
|
|
|
| HInstruction* empty_fixed_array = Add<HConstant>(
|
| isolate()->factory()->empty_fixed_array());
|
| @@ -1222,7 +1222,7 @@ HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
|
| HValue* object,
|
| HValue* key,
|
| HValue* val,
|
| - HCheckMaps* mapcheck,
|
| + HCheckMaps* checked_object,
|
| bool is_js_array,
|
| ElementsKind elements_kind,
|
| bool is_store,
|
| @@ -1237,13 +1237,14 @@ HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
|
| // generated store code.
|
| if ((elements_kind == FAST_HOLEY_ELEMENTS) ||
|
| (elements_kind == FAST_ELEMENTS && is_store)) {
|
| - if (mapcheck != NULL) {
|
| - mapcheck->ClearGVNFlag(kDependsOnElementsKind);
|
| + if (checked_object != NULL) {
|
| + checked_object->ClearGVNFlag(kDependsOnElementsKind);
|
| }
|
| }
|
| + if (checked_object != NULL) object = checked_object;
|
| bool fast_smi_only_elements = IsFastSmiElementsKind(elements_kind);
|
| bool fast_elements = IsFastObjectElementsKind(elements_kind);
|
| - HValue* elements = AddLoadElements(object, mapcheck);
|
| + HValue* elements = AddLoadElements(object);
|
| if (is_store && (fast_elements || fast_smi_only_elements) &&
|
| store_mode != STORE_NO_TRANSITION_HANDLE_COW) {
|
| HCheckMaps* check_cow_map = Add<HCheckMaps>(
|
| @@ -1252,8 +1253,8 @@ HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
|
| }
|
| HInstruction* length = NULL;
|
| if (is_js_array) {
|
| - length = Add<HLoadNamedField>(object,
|
| - HObjectAccess::ForArrayLength(elements_kind), mapcheck);
|
| + length = Add<HLoadNamedField>(
|
| + object, HObjectAccess::ForArrayLength(elements_kind));
|
| } else {
|
| length = AddLoadFixedArrayLength(elements);
|
| }
|
| @@ -1283,7 +1284,7 @@ HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
|
| Add<HLoadExternalArrayPointer>(elements);
|
| return AddExternalArrayElementAccess(
|
| external_elements, checked_key, val,
|
| - mapcheck, elements_kind, is_store);
|
| + checked_object, elements_kind, is_store);
|
| }
|
| }
|
| ASSERT(fast_smi_only_elements ||
|
| @@ -1320,7 +1321,7 @@ HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
|
| }
|
| }
|
| }
|
| - return AddFastElementAccess(elements, checked_key, val, mapcheck,
|
| + return AddFastElementAccess(elements, checked_key, val, checked_object,
|
| elements_kind, is_store, load_mode, store_mode);
|
| }
|
|
|
| @@ -1493,11 +1494,8 @@ HInstruction* HGraphBuilder::AddFastElementAccess(
|
| }
|
|
|
|
|
| -HLoadNamedField* HGraphBuilder::AddLoadElements(HValue* object,
|
| - HValue* typecheck) {
|
| - return Add<HLoadNamedField>(object,
|
| - HObjectAccess::ForElementsPointer(),
|
| - typecheck);
|
| +HLoadNamedField* HGraphBuilder::AddLoadElements(HValue* object) {
|
| + return Add<HLoadNamedField>(object, HObjectAccess::ForElementsPointer());
|
| }
|
|
|
|
|
| @@ -1700,7 +1698,7 @@ HValue* HGraphBuilder::BuildCloneShallowArray(HValue* boilerplate,
|
| if (length > 0) {
|
| // Get hold of the elements array of the boilerplate and setup the
|
| // elements pointer in the resulting object.
|
| - HValue* boilerplate_elements = AddLoadElements(boilerplate, NULL);
|
| + HValue* boilerplate_elements = AddLoadElements(boilerplate);
|
| HValue* object_elements = Add<HInnerAllocatedObject>(object, elems_offset);
|
| Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(),
|
| object_elements);
|
| @@ -1833,7 +1831,7 @@ HValue* HGraphBuilder::JSArrayBuilder::EmitMapCode() {
|
| // map, because we can just load the map in that case.
|
| HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap();
|
| return builder()->AddInstruction(
|
| - builder()->BuildLoadNamedField(constructor_function_, access, NULL));
|
| + builder()->BuildLoadNamedField(constructor_function_, access));
|
| }
|
|
|
| HInstruction* native_context = builder()->BuildGetNativeContext();
|
| @@ -1854,7 +1852,7 @@ HValue* HGraphBuilder::JSArrayBuilder::EmitInternalMapCode() {
|
| // Find the map near the constructor function
|
| HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap();
|
| return builder()->AddInstruction(
|
| - builder()->BuildLoadNamedField(constructor_function_, access, NULL));
|
| + builder()->BuildLoadNamedField(constructor_function_, access));
|
| }
|
|
|
|
|
| @@ -4298,7 +4296,6 @@ void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
|
| int data_size = 0;
|
| int pointer_size = 0;
|
| int max_properties = kMaxFastLiteralProperties;
|
| - HCheckMaps* type_check = NULL;
|
| if (IsFastLiteral(original_boilerplate_object,
|
| kMaxFastLiteralDepth,
|
| &max_properties,
|
| @@ -4336,7 +4333,7 @@ void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
|
| // De-opt if elements kind changed from boilerplate_elements_kind.
|
| Handle<Map> map = Handle<Map>(original_boilerplate_object->map(),
|
| isolate());
|
| - type_check = Add<HCheckMaps>(literal, map, top_info());
|
| + literal = Add<HCheckMaps>(literal, map, top_info());
|
| }
|
|
|
| // The array is expected in the bailout environment during computation
|
| @@ -4357,7 +4354,7 @@ void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
|
| HValue* value = Pop();
|
| if (!Smi::IsValid(i)) return Bailout(kNonSmiKeyInArrayLiteral);
|
|
|
| - elements = AddLoadElements(literal, type_check);
|
| + elements = AddLoadElements(literal);
|
|
|
| HValue* key = Add<HConstant>(i);
|
|
|
| @@ -4580,8 +4577,8 @@ HInstruction* HOptimizedGraphBuilder::TryLoadPolymorphicAsMonomorphic(
|
| if (count == types->length()) {
|
| // Everything matched; can use monomorphic load.
|
| BuildCheckHeapObject(object);
|
| - HCheckMaps* type_check = Add<HCheckMaps>(object, types);
|
| - return BuildLoadNamedField(object, access, type_check);
|
| + HCheckMaps* checked_object = Add<HCheckMaps>(object, types);
|
| + return BuildLoadNamedField(checked_object, access);
|
| }
|
|
|
| if (count != 0) return NULL;
|
| @@ -4602,14 +4599,14 @@ HInstruction* HOptimizedGraphBuilder::TryLoadPolymorphicAsMonomorphic(
|
| if (!lookup.IsField()) return NULL;
|
|
|
| BuildCheckHeapObject(object);
|
| - HCheckMaps* type_check = Add<HCheckMaps>(object, types);
|
| + Add<HCheckMaps>(object, types);
|
|
|
| Handle<JSObject> holder(lookup.holder());
|
| Handle<Map> holder_map(holder->map());
|
| - BuildCheckPrototypeMaps(Handle<JSObject>::cast(prototype), holder);
|
| - HValue* holder_value = Add<HConstant>(holder);
|
| - return BuildLoadNamedField(holder_value,
|
| - HObjectAccess::ForField(holder_map, &lookup, name), type_check);
|
| + HValue* checked_holder = BuildCheckPrototypeMaps(
|
| + Handle<JSObject>::cast(prototype), holder);
|
| + return BuildLoadNamedField(checked_holder,
|
| + HObjectAccess::ForField(holder_map, &lookup, name));
|
| }
|
|
|
|
|
| @@ -4684,7 +4681,7 @@ void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField(
|
| // TODO(verwaest): Merge logic with BuildLoadNamedMonomorphic.
|
| if (lookup.IsField()) {
|
| HObjectAccess access = HObjectAccess::ForField(map, &lookup, name);
|
| - HLoadNamedField* load = BuildLoadNamedField(object, access, compare);
|
| + HLoadNamedField* load = BuildLoadNamedField(compare, access);
|
| load->set_position(expr->position());
|
| AddInstruction(load);
|
| if (!ast_context()->IsEffect()) Push(load);
|
| @@ -5357,32 +5354,29 @@ void HOptimizedGraphBuilder::VisitThrow(Throw* expr) {
|
|
|
|
|
| HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object,
|
| - HObjectAccess access,
|
| - HValue* typecheck) {
|
| + HObjectAccess access) {
|
| if (FLAG_track_double_fields && access.representation().IsDouble()) {
|
| // load the heap number
|
| HLoadNamedField* heap_number = Add<HLoadNamedField>(
|
| object, access.WithRepresentation(Representation::Tagged()));
|
| heap_number->set_type(HType::HeapNumber());
|
| // load the double value from it
|
| - return New<HLoadNamedField>(heap_number,
|
| - HObjectAccess::ForHeapNumberValue(),
|
| - typecheck);
|
| + return New<HLoadNamedField>(
|
| + heap_number, HObjectAccess::ForHeapNumberValue());
|
| }
|
| - return New<HLoadNamedField>(object, access, typecheck);
|
| + return New<HLoadNamedField>(object, access);
|
| }
|
|
|
|
|
| HInstruction* HGraphBuilder::BuildLoadStringLength(HValue* object,
|
| - HValue* typecheck) {
|
| + HValue* checked_string) {
|
| if (FLAG_fold_constants && object->IsConstant()) {
|
| HConstant* constant = HConstant::cast(object);
|
| if (constant->HasStringValue()) {
|
| return New<HConstant>(constant->StringValue()->length());
|
| }
|
| }
|
| - return BuildLoadNamedField(
|
| - object, HObjectAccess::ForStringLength(), typecheck);
|
| + return BuildLoadNamedField(checked_string, HObjectAccess::ForStringLength());
|
| }
|
|
|
|
|
| @@ -5421,18 +5415,18 @@ HInstruction* HOptimizedGraphBuilder::BuildLoadNamedMonomorphic(
|
| // Handle access to various length properties
|
| if (name->Equals(isolate()->heap()->length_string())) {
|
| if (map->instance_type() == JS_ARRAY_TYPE) {
|
| - HCheckMaps* type_check = AddCheckMap(object, map);
|
| - return New<HLoadNamedField>(object,
|
| - HObjectAccess::ForArrayLength(map->elements_kind()), type_check);
|
| + HCheckMaps* checked_object = AddCheckMap(object, map);
|
| + return New<HLoadNamedField>(
|
| + checked_object, HObjectAccess::ForArrayLength(map->elements_kind()));
|
| }
|
| }
|
|
|
| LookupResult lookup(isolate());
|
| map->LookupDescriptor(NULL, *name, &lookup);
|
| if (lookup.IsField()) {
|
| - HCheckMaps* type_check = AddCheckMap(object, map);
|
| - return BuildLoadNamedField(object,
|
| - HObjectAccess::ForField(map, &lookup, name), type_check);
|
| + HCheckMaps* checked_object = AddCheckMap(object, map);
|
| + return BuildLoadNamedField(
|
| + checked_object, HObjectAccess::ForField(map, &lookup, name));
|
| }
|
|
|
| // Handle a load of a constant known function.
|
| @@ -5448,11 +5442,10 @@ HInstruction* HOptimizedGraphBuilder::BuildLoadNamedMonomorphic(
|
| Handle<JSObject> prototype(JSObject::cast(map->prototype()));
|
| Handle<JSObject> holder(lookup.holder());
|
| Handle<Map> holder_map(holder->map());
|
| - HCheckMaps* type_check = AddCheckMap(object, map);
|
| - BuildCheckPrototypeMaps(prototype, holder);
|
| - HValue* holder_value = Add<HConstant>(holder);
|
| - return BuildLoadNamedField(holder_value,
|
| - HObjectAccess::ForField(holder_map, &lookup, name), type_check);
|
| + AddCheckMap(object, map);
|
| + HValue* checked_holder = BuildCheckPrototypeMaps(prototype, holder);
|
| + return BuildLoadNamedField(
|
| + checked_holder, HObjectAccess::ForField(holder_map, &lookup, name));
|
| }
|
|
|
| // Handle a load of a constant function somewhere in the prototype chain.
|
| @@ -5645,11 +5638,11 @@ HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess(
|
| return is_store ? NULL : instr;
|
| }
|
|
|
| - HInstruction* checkspec =
|
| + HInstruction* checked_object =
|
| AddInstruction(HCheckInstanceType::NewIsSpecObject(object, zone()));
|
| HBasicBlock* join = graph()->CreateBasicBlock();
|
|
|
| - HInstruction* elements = AddLoadElements(object, checkspec);
|
| + HInstruction* elements = AddLoadElements(checked_object);
|
|
|
| for (int i = 0; i < untransitionable_maps.length(); ++i) {
|
| Handle<Map> map = untransitionable_maps[i];
|
| @@ -5671,7 +5664,7 @@ HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess(
|
| }
|
| if (map->instance_type() == JS_ARRAY_TYPE) {
|
| HInstruction* length = Add<HLoadNamedField>(
|
| - object, HObjectAccess::ForArrayLength(elements_kind), mapcompare);
|
| + mapcompare, HObjectAccess::ForArrayLength(elements_kind));
|
| checked_key = Add<HBoundsCheck>(key, length);
|
| } else {
|
| HInstruction* length = AddLoadFixedArrayLength(elements);
|
| @@ -5947,30 +5940,34 @@ void HOptimizedGraphBuilder::VisitProperty(Property* expr) {
|
| }
|
|
|
|
|
| -void HGraphBuilder::BuildConstantMapCheck(Handle<JSObject> constant,
|
| - CompilationInfo* info) {
|
| +HInstruction* HGraphBuilder::BuildConstantMapCheck(Handle<JSObject> constant,
|
| + CompilationInfo* info) {
|
| HConstant* constant_value = New<HConstant>(constant);
|
|
|
| if (constant->map()->CanOmitMapChecks()) {
|
| constant->map()->AddDependentCompilationInfo(
|
| DependentCode::kPrototypeCheckGroup, info);
|
| - return;
|
| + return constant_value;
|
| }
|
|
|
| AddInstruction(constant_value);
|
| HCheckMaps* check =
|
| Add<HCheckMaps>(constant_value, handle(constant->map()), info);
|
| check->ClearGVNFlag(kDependsOnElementsKind);
|
| + return check;
|
| }
|
|
|
|
|
| -void HGraphBuilder::BuildCheckPrototypeMaps(Handle<JSObject> prototype,
|
| - Handle<JSObject> holder) {
|
| - BuildConstantMapCheck(prototype, top_info());
|
| +HInstruction* HGraphBuilder::BuildCheckPrototypeMaps(Handle<JSObject> prototype,
|
| + Handle<JSObject> holder) {
|
| while (!prototype.is_identical_to(holder)) {
|
| - prototype = handle(JSObject::cast(prototype->GetPrototype()));
|
| BuildConstantMapCheck(prototype, top_info());
|
| + prototype = handle(JSObject::cast(prototype->GetPrototype()));
|
| }
|
| +
|
| + HInstruction* checked_object = BuildConstantMapCheck(prototype, top_info());
|
| + if (!checked_object->IsLinked()) AddInstruction(checked_object);
|
| + return checked_object;
|
| }
|
|
|
|
|
|
|