HObjectAccess access = HObjectAccess::ForAllocationSiteTransitionInfo();
HInstruction* boilerplate = Add<HLoadNamedField>(allocation_site, access);
if (mode == FastCloneShallowArrayStub::CLONE_ANY_ELEMENTS) {
- HValue* elements = AddLoadElements(boilerplate);
+ HValue* elements = AddLoadElements(boilerplate, NULL);
IfBuilder if_fixed_cow(this);
if_fixed_cow.If<HCompareMap>(elements, factory->fixed_cow_array_map());
HObjectAccess access = casted_stub()->is_inobject() ?
HObjectAccess::ForJSObjectOffset(casted_stub()->offset(), rep) :
HObjectAccess::ForBackingStoreOffset(casted_stub()->offset(), rep);
- return AddInstruction(BuildLoadNamedField(GetParameter(0), access));
+ return AddInstruction(BuildLoadNamedField(GetParameter(0), access, NULL));
}
HObjectAccess access = casted_stub()->is_inobject() ?
HObjectAccess::ForJSObjectOffset(casted_stub()->offset(), rep) :
HObjectAccess::ForBackingStoreOffset(casted_stub()->offset(), rep);
- return AddInstruction(BuildLoadNamedField(GetParameter(0), access));
+ return AddInstruction(BuildLoadNamedField(GetParameter(0), access, NULL));
}
}
if (!IsSimpleMapChangeTransition(from_kind, to_kind)) {
- HInstruction* elements = AddLoadElements(object);
+ HInstruction* elements = AddLoadElements(object, NULL);
HInstruction* empty_fixed_array = Add<HConstant>(
isolate()->factory()->empty_fixed_array());
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);
+ HValue* boilerplate_elements = AddLoadElements(boilerplate, NULL);
HValue* object_elements = Add<HInnerAllocatedObject>(object, elems_offset);
Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(),
object_elements);
// map, because we can just load the map in that case.
HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap();
return builder()->AddInstruction(
- builder()->BuildLoadNamedField(constructor_function_, access));
+ builder()->BuildLoadNamedField(constructor_function_, access, NULL));
}
HInstruction* native_context = builder()->BuildGetNativeContext();
// Find the map near the constructor function
HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap();
return builder()->AddInstruction(
- builder()->BuildLoadNamedField(constructor_function_, access));
+ builder()->BuildLoadNamedField(constructor_function_, access, NULL));
}
int data_size = 0;
int pointer_size = 0;
int max_properties = kMaxFastLiteralProperties;
+ HCheckMaps* type_check = NULL;
if (IsFastLiteral(original_boilerplate_object,
kMaxFastLiteralDepth,
&max_properties,
// De-opt if elements kind changed from boilerplate_elements_kind.
Handle<Map> map = Handle<Map>(original_boilerplate_object->map(),
isolate());
- Add<HCheckMaps>(literal, map, top_info());
+ type_check = Add<HCheckMaps>(literal, map, top_info());
}
// The array is expected in the bailout environment during computation
HValue* value = Pop();
if (!Smi::IsValid(i)) return Bailout(kNonSmiKeyInArrayLiteral);
- elements = AddLoadElements(literal);
+ elements = AddLoadElements(literal, type_check);
HValue* key = Add<HConstant>(i);
}
-void HOptimizedGraphBuilder::AddCheckMap(HValue* object, Handle<Map> map) {
+HCheckMaps* HOptimizedGraphBuilder::AddCheckMap(HValue* object,
+ Handle<Map> map) {
BuildCheckHeapObject(object);
- Add<HCheckMaps>(object, map, top_info());
+ return Add<HCheckMaps>(object, map, top_info());
}
if (count == types->length()) {
// Everything matched; can use monomorphic load.
BuildCheckHeapObject(object);
- Add<HCheckMaps>(object, types);
- return BuildLoadNamedField(object, access);
+ HCheckMaps* type_check = Add<HCheckMaps>(object, types);
+ return BuildLoadNamedField(object, access, type_check);
}
if (count != 0) return NULL;
if (!lookup.IsField()) return NULL;
BuildCheckHeapObject(object);
- Add<HCheckMaps>(object, types);
+ HCheckMaps* type_check = 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));
+ HObjectAccess::ForField(holder_map, &lookup, name), type_check);
}
// TODO(verwaest): Merge logic with BuildLoadNamedMonomorphic.
if (lookup.IsField()) {
HObjectAccess access = HObjectAccess::ForField(map, &lookup, name);
- HLoadNamedField* load = BuildLoadNamedField(object, access);
+ HLoadNamedField* load = BuildLoadNamedField(object, access, compare);
load->set_position(expr->position());
AddInstruction(load);
if (!ast_context()->IsEffect()) Push(load);
// Handle access to various length properties
if (name->Equals(isolate()->heap()->length_string())) {
if (map->instance_type() == JS_ARRAY_TYPE) {
- AddCheckMap(object, map);
+ HCheckMaps* type_check = AddCheckMap(object, map);
return New<HLoadNamedField>(object,
- HObjectAccess::ForArrayLength(map->elements_kind()));
+ HObjectAccess::ForArrayLength(map->elements_kind()), type_check);
}
}
LookupResult lookup(isolate());
map->LookupDescriptor(NULL, *name, &lookup);
if (lookup.IsField()) {
- AddCheckMap(object, map);
+ HCheckMaps* type_check = AddCheckMap(object, map);
return BuildLoadNamedField(object,
- HObjectAccess::ForField(map, &lookup, name));
+ HObjectAccess::ForField(map, &lookup, name), type_check);
}
// Handle a load of a constant known function.
Handle<JSObject> prototype(JSObject::cast(map->prototype()));
Handle<JSObject> holder(lookup.holder());
Handle<Map> holder_map(holder->map());
- AddCheckMap(object, 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));
+ HObjectAccess::ForField(holder_map, &lookup, name), type_check);
}
// Handle a load of a constant function somewhere in the prototype chain.
--- /dev/null
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --allow-natives-syntax
+
+// Load fields should not be hoisted beyond their check maps when the check maps
+// cannot be hoisted due to changes in elements kinds.
+function f(o, a) {
+ var v;
+ var i = 1;
+ while (i < 2) {
+ v = o.y;
+ a[0] = 1.5;
+ i++;
+ }
+ return v;
+}
+
+f({y:1.4}, [1]);
+f({y:1.6}, [1]);
+%OptimizeFunctionOnNextCall(f);
+f({x:1}, [1]);
+
+// Polymorphic loads should not be hoisted beyond their compare maps.
+function f2(o) {
+ var i = 0;
+ var v;
+ while (i < 1) {
+ v = o.x;
+ i++;
+ }
+ return v;
+}
+
+var o1 = { x: 1.5 };
+var o2 = { y: 1, x: 1 };
+
+f2(o1);
+f2(o1);
+f2(o2);
+%OptimizeFunctionOnNextCall(f2);
+f2(o2);