Revert of [turbofan] Initial support for monomorphic/polymorphic property loads. (patchset #3 id:100001 of https://codereview.chromium.org/1396333010/ )
Reason for revert: Waterfall redness. Original issue's description: > [turbofan] Initial support for monomorphic/polymorphic property loads. > > Native context specialization now lowers monomorphic and > polymorphic accesses to data and constant data properties on > object and/or prototype chain. We don't deal with accessors > yet, and we also completely ignore proxies (which is compatible > with what Crankshaft does). > > The code is more or less the straightforward implementation. We > will need to refactor that and extract common patterns once the > remaining bits for full load/store support is in. > > CQ_INCLUDE_TRYBOTS=tryserver.v8:v8_linux_nosnap_rel > R=jarin@chromium.org > BUG=v8:4470 > LOG=n > > Committed: https://crrev.com/3a0bf860b7177f7abef01ff308a53603389d958e > Cr-Commit-Position: refs/heads/master@{#31340} TBR=bmeurer@chromium.org NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true BUG=v8:4470 Review URL: https://codereview.chromium.org/1408123002 Cr-Commit-Position: refs/heads/master@{#31341}
This commit is contained in:
parent
3a0bf860b7
commit
5c53481233
@ -106,15 +106,6 @@ void CompilationDependencies::Rollback() {
|
||||
}
|
||||
|
||||
|
||||
void CompilationDependencies::AssumeMapStable(Handle<Map> map) {
|
||||
DCHECK(map->is_stable());
|
||||
// Do nothing if the map cannot transition.
|
||||
if (map->CanTransition()) {
|
||||
Insert(DependentCode::kPrototypeCheckGroup, map);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CompilationDependencies::AssumeTransitionStable(
|
||||
Handle<AllocationSite> site) {
|
||||
// Do nothing if the object doesn't have any useful element transitions left.
|
||||
|
@ -31,7 +31,6 @@ class CompilationDependencies {
|
||||
void AssumeFieldType(Handle<Map> map) {
|
||||
Insert(DependentCode::kFieldTypeGroup, map);
|
||||
}
|
||||
void AssumeMapStable(Handle<Map> map);
|
||||
void AssumePropertyCell(Handle<PropertyCell> cell) {
|
||||
Insert(DependentCode::kPropertyCellChangedGroup, cell);
|
||||
}
|
||||
|
@ -9,10 +9,8 @@
|
||||
#include "src/compiler/js-graph.h"
|
||||
#include "src/compiler/js-operator.h"
|
||||
#include "src/contexts.h"
|
||||
#include "src/field-index-inl.h"
|
||||
#include "src/lookup.h"
|
||||
#include "src/objects-inl.h" // TODO(mstarzinger): Temporary cycle breaker!
|
||||
#include "src/type-feedback-vector.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
@ -27,14 +25,12 @@ struct JSGlobalSpecialization::ScriptContextTableLookupResult {
|
||||
|
||||
JSGlobalSpecialization::JSGlobalSpecialization(
|
||||
Editor* editor, JSGraph* jsgraph, Flags flags,
|
||||
Handle<GlobalObject> global_object, CompilationDependencies* dependencies,
|
||||
Zone* zone)
|
||||
Handle<GlobalObject> global_object, CompilationDependencies* dependencies)
|
||||
: AdvancedReducer(editor),
|
||||
jsgraph_(jsgraph),
|
||||
flags_(flags),
|
||||
global_object_(global_object),
|
||||
dependencies_(dependencies),
|
||||
zone_(zone) {}
|
||||
dependencies_(dependencies) {}
|
||||
|
||||
|
||||
Reduction JSGlobalSpecialization::Reduce(Node* node) {
|
||||
@ -43,8 +39,6 @@ Reduction JSGlobalSpecialization::Reduce(Node* node) {
|
||||
return ReduceJSLoadGlobal(node);
|
||||
case IrOpcode::kJSStoreGlobal:
|
||||
return ReduceJSStoreGlobal(node);
|
||||
case IrOpcode::kJSLoadNamed:
|
||||
return ReduceJSLoadNamed(node);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -236,359 +230,11 @@ Reduction JSGlobalSpecialization::ReduceJSStoreGlobal(Node* node) {
|
||||
}
|
||||
|
||||
|
||||
// This class encapsulates all information required to access a certain
|
||||
// object property, either on the object itself or on the prototype chain.
|
||||
class JSGlobalSpecialization::PropertyAccessInfo final {
|
||||
public:
|
||||
enum Kind { kInvalid, kData, kDataConstant };
|
||||
|
||||
static PropertyAccessInfo DataConstant(Type* receiver_type,
|
||||
Handle<Object> constant,
|
||||
MaybeHandle<JSObject> holder) {
|
||||
return PropertyAccessInfo(holder, constant, receiver_type);
|
||||
}
|
||||
static PropertyAccessInfo Data(Type* receiver_type, FieldIndex field_index,
|
||||
Representation field_representation,
|
||||
MaybeHandle<JSObject> holder) {
|
||||
return PropertyAccessInfo(holder, field_index, field_representation,
|
||||
receiver_type);
|
||||
}
|
||||
|
||||
PropertyAccessInfo() : kind_(kInvalid) {}
|
||||
PropertyAccessInfo(MaybeHandle<JSObject> holder, Handle<Object> constant,
|
||||
Type* receiver_type)
|
||||
: kind_(kDataConstant),
|
||||
receiver_type_(receiver_type),
|
||||
constant_(constant),
|
||||
holder_(holder) {}
|
||||
PropertyAccessInfo(MaybeHandle<JSObject> holder, FieldIndex field_index,
|
||||
Representation field_representation, Type* receiver_type)
|
||||
: kind_(kData),
|
||||
receiver_type_(receiver_type),
|
||||
holder_(holder),
|
||||
field_index_(field_index),
|
||||
field_representation_(field_representation) {}
|
||||
|
||||
bool IsDataConstant() const { return kind() == kDataConstant; }
|
||||
bool IsData() const { return kind() == kData; }
|
||||
|
||||
Kind kind() const { return kind_; }
|
||||
MaybeHandle<JSObject> holder() const { return holder_; }
|
||||
Handle<Object> constant() const { return constant_; }
|
||||
FieldIndex field_index() const { return field_index_; }
|
||||
Representation field_representation() const { return field_representation_; }
|
||||
Type* receiver_type() const { return receiver_type_; }
|
||||
|
||||
private:
|
||||
Kind kind_;
|
||||
Type* receiver_type_;
|
||||
Handle<Object> constant_;
|
||||
MaybeHandle<JSObject> holder_;
|
||||
FieldIndex field_index_;
|
||||
Representation field_representation_;
|
||||
};
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
bool CanInlinePropertyAccess(Handle<Map> map) {
|
||||
// TODO(bmeurer): Do something about the number stuff.
|
||||
if (map->instance_type() == HEAP_NUMBER_TYPE) return false;
|
||||
if (map->instance_type() < FIRST_NONSTRING_TYPE) return true;
|
||||
return map->IsJSObjectMap() && !map->is_dictionary_map() &&
|
||||
!map->has_named_interceptor() &&
|
||||
// TODO(verwaest): Whitelist contexts to which we have access.
|
||||
!map->is_access_check_needed();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
bool JSGlobalSpecialization::ComputePropertyAccessInfo(
|
||||
Handle<Map> map, Handle<Name> name, PropertyAccessInfo* access_info) {
|
||||
MaybeHandle<JSObject> holder;
|
||||
Type* receiver_type = Type::Class(map, graph()->zone());
|
||||
while (CanInlinePropertyAccess(map)) {
|
||||
// Lookup the named property on the {map}.
|
||||
Handle<DescriptorArray> descriptors(map->instance_descriptors(), isolate());
|
||||
int const number = descriptors->SearchWithCache(*name, *map);
|
||||
if (number != DescriptorArray::kNotFound) {
|
||||
PropertyDetails const details = descriptors->GetDetails(number);
|
||||
if (details.type() == DATA_CONSTANT) {
|
||||
*access_info = PropertyAccessInfo::DataConstant(
|
||||
receiver_type, handle(descriptors->GetValue(number), isolate()),
|
||||
holder);
|
||||
return true;
|
||||
} else if (details.type() == DATA) {
|
||||
int index = descriptors->GetFieldIndex(number);
|
||||
Representation field_representation = details.representation();
|
||||
FieldIndex field_index = FieldIndex::ForPropertyIndex(
|
||||
*map, index, field_representation.IsDouble());
|
||||
*access_info = PropertyAccessInfo::Data(receiver_type, field_index,
|
||||
field_representation, holder);
|
||||
return true;
|
||||
} else {
|
||||
// TODO(bmeurer): Add support for accessors.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Don't search on the prototype chain for special indices in case of
|
||||
// integer indexed exotic objects (see ES6 section 9.4.5).
|
||||
if (map->IsJSTypedArrayMap() && name->IsString() &&
|
||||
IsSpecialIndex(isolate()->unicode_cache(), String::cast(*name))) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Walk up the prototype chain.
|
||||
if (!map->prototype()->IsJSObject()) {
|
||||
// TODO(bmeurer): Handle the not found case if the prototype is null.
|
||||
break;
|
||||
}
|
||||
Handle<JSObject> map_prototype(JSObject::cast(map->prototype()), isolate());
|
||||
if (map_prototype->map()->is_deprecated()) {
|
||||
// Try to migrate the prototype object so we don't embed the deprecated
|
||||
// map into the optimized code.
|
||||
JSObject::TryMigrateInstance(map_prototype);
|
||||
}
|
||||
map = handle(map_prototype->map(), isolate());
|
||||
holder = map_prototype;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool JSGlobalSpecialization::ComputePropertyAccessInfos(
|
||||
MapHandleList const& maps, Handle<Name> name,
|
||||
ZoneVector<PropertyAccessInfo>* access_infos) {
|
||||
for (Handle<Map> map : maps) {
|
||||
PropertyAccessInfo access_info;
|
||||
if (!ComputePropertyAccessInfo(map, name, &access_info)) return false;
|
||||
access_infos->push_back(access_info);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Reduction JSGlobalSpecialization::ReduceJSLoadNamed(Node* node) {
|
||||
DCHECK_EQ(IrOpcode::kJSLoadNamed, node->opcode());
|
||||
LoadNamedParameters const p = LoadNamedParametersOf(node->op());
|
||||
Handle<Name> name = p.name();
|
||||
Node* receiver = NodeProperties::GetValueInput(node, 0);
|
||||
Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
|
||||
Node* effect = NodeProperties::GetEffectInput(node);
|
||||
Node* control = NodeProperties::GetControlInput(node);
|
||||
|
||||
// Not much we can do if deoptimization support is disabled.
|
||||
if (!(flags() & kDeoptimizationEnabled)) return NoChange();
|
||||
|
||||
// Extract receiver maps from the LOAD_IC using the LoadICNexus.
|
||||
MapHandleList receiver_maps;
|
||||
if (!p.feedback().IsValid()) return NoChange();
|
||||
LoadICNexus nexus(p.feedback().vector(), p.feedback().slot());
|
||||
if (nexus.ExtractMaps(&receiver_maps) == 0) return NoChange();
|
||||
DCHECK_LT(0, receiver_maps.length());
|
||||
|
||||
// Compute property access infos for the receiver maps.
|
||||
ZoneVector<PropertyAccessInfo> access_infos(zone());
|
||||
if (!ComputePropertyAccessInfos(receiver_maps, name, &access_infos)) {
|
||||
return NoChange();
|
||||
}
|
||||
DCHECK(!access_infos.empty());
|
||||
|
||||
// The final states for every polymorphic branch. We join them with
|
||||
// Merge+Phi+EffectPhi at the bottom.
|
||||
ZoneVector<Node*> values(zone());
|
||||
ZoneVector<Node*> effects(zone());
|
||||
ZoneVector<Node*> controls(zone());
|
||||
|
||||
// The list of "exiting" controls, which currently go to a single deoptimize.
|
||||
// TODO(bmeurer): Consider using an IC as fallback.
|
||||
Node* const exit_effect = effect;
|
||||
ZoneVector<Node*> exit_controls(zone());
|
||||
|
||||
// Ensure that {receiver} is a heap object.
|
||||
Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), receiver);
|
||||
Node* branch =
|
||||
graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control);
|
||||
exit_controls.push_back(graph()->NewNode(common()->IfTrue(), branch));
|
||||
control = graph()->NewNode(common()->IfFalse(), branch);
|
||||
|
||||
// Load the {receiver} map. The resulting effect is the dominating effect for
|
||||
// all (polymorphic) branches.
|
||||
Node* receiver_map = effect =
|
||||
graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
|
||||
receiver, effect, control);
|
||||
|
||||
// Generate code for the various different property access patterns.
|
||||
Node* fallthrough_control = control;
|
||||
for (PropertyAccessInfo const& access_info : access_infos) {
|
||||
Node* this_value = receiver;
|
||||
Node* this_effect = effect;
|
||||
Node* this_control;
|
||||
|
||||
// Perform map check on {receiver}.
|
||||
Type* receiver_type = access_info.receiver_type();
|
||||
if (receiver_type->Is(Type::String())) {
|
||||
// Emit an instance type check for strings.
|
||||
Node* receiver_instance_type = this_effect = graph()->NewNode(
|
||||
simplified()->LoadField(AccessBuilder::ForMapInstanceType()),
|
||||
receiver_map, this_effect, fallthrough_control);
|
||||
Node* check =
|
||||
graph()->NewNode(machine()->Uint32LessThan(), receiver_instance_type,
|
||||
jsgraph()->Uint32Constant(FIRST_NONSTRING_TYPE));
|
||||
Node* branch = graph()->NewNode(common()->Branch(BranchHint::kTrue),
|
||||
check, fallthrough_control);
|
||||
fallthrough_control = graph()->NewNode(common()->IfFalse(), branch);
|
||||
this_control = graph()->NewNode(common()->IfTrue(), branch);
|
||||
} else {
|
||||
// Emit a (sequence of) map checks for other properties.
|
||||
ZoneVector<Node*> this_controls(zone());
|
||||
for (auto i = access_info.receiver_type()->Classes(); !i.Done();
|
||||
i.Advance()) {
|
||||
Handle<Map> map = i.Current();
|
||||
Node* check =
|
||||
graph()->NewNode(simplified()->ReferenceEqual(Type::Internal()),
|
||||
receiver_map, jsgraph()->Constant(map));
|
||||
Node* branch = graph()->NewNode(common()->Branch(BranchHint::kTrue),
|
||||
check, fallthrough_control);
|
||||
this_controls.push_back(graph()->NewNode(common()->IfTrue(), branch));
|
||||
fallthrough_control = graph()->NewNode(common()->IfFalse(), branch);
|
||||
}
|
||||
int const this_control_count = static_cast<int>(this_controls.size());
|
||||
this_control =
|
||||
(this_control_count == 1)
|
||||
? this_controls.front()
|
||||
: graph()->NewNode(common()->Merge(this_control_count),
|
||||
this_control_count, &this_controls.front());
|
||||
}
|
||||
|
||||
// Determine actual holder and perform prototype chain checks.
|
||||
Handle<JSObject> holder;
|
||||
if (access_info.holder().ToHandle(&holder)) {
|
||||
this_value = jsgraph()->Constant(holder);
|
||||
for (auto i = access_info.receiver_type()->Classes(); !i.Done();
|
||||
i.Advance()) {
|
||||
Handle<Map> map = i.Current();
|
||||
PrototypeIterator j(map);
|
||||
while (true) {
|
||||
// Check that the {prototype} still has the same map. For stable
|
||||
// maps, we can add a stability dependency on the prototype map;
|
||||
// for everything else we need to perform a map check at runtime.
|
||||
Handle<JSReceiver> prototype =
|
||||
PrototypeIterator::GetCurrent<JSReceiver>(j);
|
||||
if (prototype->map()->is_stable()) {
|
||||
dependencies()->AssumeMapStable(
|
||||
handle(prototype->map(), isolate()));
|
||||
} else {
|
||||
Node* prototype_map = this_effect = graph()->NewNode(
|
||||
simplified()->LoadField(AccessBuilder::ForMap()),
|
||||
jsgraph()->Constant(prototype), this_effect, this_control);
|
||||
Node* check = graph()->NewNode(
|
||||
simplified()->ReferenceEqual(Type::Internal()), prototype_map,
|
||||
jsgraph()->Constant(handle(prototype->map(), isolate())));
|
||||
Node* branch = graph()->NewNode(common()->Branch(BranchHint::kTrue),
|
||||
check, this_control);
|
||||
exit_controls.push_back(
|
||||
graph()->NewNode(common()->IfFalse(), branch));
|
||||
this_control = graph()->NewNode(common()->IfTrue(), branch);
|
||||
}
|
||||
// Stop once we get to the holder.
|
||||
if (prototype.is_identical_to(holder)) break;
|
||||
j.Advance();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Generate the actual property access.
|
||||
if (access_info.IsDataConstant()) {
|
||||
this_value = jsgraph()->Constant(access_info.constant());
|
||||
} else {
|
||||
// TODO(bmeurer): This is sort of adhoc, and must be refactored into some
|
||||
// common code once we also have support for stores.
|
||||
DCHECK(access_info.IsData());
|
||||
FieldIndex const field_index = access_info.field_index();
|
||||
Representation const field_representation =
|
||||
access_info.field_representation();
|
||||
if (!field_index.is_inobject()) {
|
||||
this_value = this_effect = graph()->NewNode(
|
||||
simplified()->LoadField(AccessBuilder::ForJSObjectProperties()),
|
||||
this_value, this_effect, this_control);
|
||||
}
|
||||
FieldAccess field_access;
|
||||
field_access.base_is_tagged = kTaggedBase;
|
||||
field_access.offset = field_index.offset();
|
||||
field_access.name = name;
|
||||
field_access.type = Type::Any();
|
||||
field_access.machine_type = kMachAnyTagged;
|
||||
if (field_representation.IsSmi()) {
|
||||
field_access.type = Type::Intersect(
|
||||
Type::SignedSmall(), Type::TaggedSigned(), graph()->zone());
|
||||
} else if (field_representation.IsDouble()) {
|
||||
if (!field_index.is_inobject() || field_index.is_hidden_field() ||
|
||||
!FLAG_unbox_double_fields) {
|
||||
this_value = this_effect =
|
||||
graph()->NewNode(simplified()->LoadField(field_access),
|
||||
this_value, this_effect, this_control);
|
||||
field_access.offset = HeapNumber::kValueOffset;
|
||||
field_access.name = MaybeHandle<Name>();
|
||||
}
|
||||
field_access.type = Type::Intersect(
|
||||
Type::Number(), Type::UntaggedFloat64(), graph()->zone());
|
||||
field_access.machine_type = kMachFloat64;
|
||||
} else if (field_representation.IsHeapObject()) {
|
||||
field_access.type = Type::TaggedPointer();
|
||||
}
|
||||
this_value = this_effect =
|
||||
graph()->NewNode(simplified()->LoadField(field_access), this_value,
|
||||
this_effect, this_control);
|
||||
}
|
||||
|
||||
// Remember the final state for this property access.
|
||||
values.push_back(this_value);
|
||||
effects.push_back(this_effect);
|
||||
controls.push_back(this_control);
|
||||
}
|
||||
|
||||
// Generate the single "exit" point, where we get if either all map/instance
|
||||
// type checks failed, or one of the assumptions inside one of the cases
|
||||
// failes (i.e. failing prototype chain check).
|
||||
// TODO(bmeurer): Consider falling back to IC here if deoptimization is
|
||||
// disabled.
|
||||
exit_controls.push_back(fallthrough_control);
|
||||
int const exit_control_count = static_cast<int>(exit_controls.size());
|
||||
Node* exit_control =
|
||||
(exit_control_count == 1)
|
||||
? exit_controls.front()
|
||||
: graph()->NewNode(common()->Merge(exit_control_count),
|
||||
exit_control_count, &exit_controls.front());
|
||||
Node* deoptimize = graph()->NewNode(common()->Deoptimize(), frame_state,
|
||||
exit_effect, exit_control);
|
||||
// TODO(bmeurer): This should be on the AdvancedReducer somehow.
|
||||
NodeProperties::MergeControlToEnd(graph(), common(), deoptimize);
|
||||
|
||||
// Generate the final merge point for all (polymorphic) branches.
|
||||
Node* value;
|
||||
int const control_count = static_cast<int>(controls.size());
|
||||
if (control_count == 1) {
|
||||
value = values.front();
|
||||
effect = effects.front();
|
||||
control = controls.front();
|
||||
} else {
|
||||
control = graph()->NewNode(common()->Merge(control_count), control_count,
|
||||
&controls.front());
|
||||
values.push_back(control);
|
||||
value = graph()->NewNode(common()->Phi(kMachAnyTagged, control_count),
|
||||
control_count + 1, &values.front());
|
||||
effects.push_back(control);
|
||||
effect = graph()->NewNode(common()->EffectPhi(control_count),
|
||||
control_count + 1, &effects.front());
|
||||
}
|
||||
return Replace(node, value, effect, control);
|
||||
}
|
||||
|
||||
|
||||
Reduction JSGlobalSpecialization::Replace(Node* node, Handle<Object> value) {
|
||||
// TODO(bmeurer): Move this to JSGraph::HeapConstant instead?
|
||||
if (value->IsConsString()) {
|
||||
value = String::Flatten(Handle<String>::cast(value), TENURED);
|
||||
}
|
||||
return Replace(node, jsgraph()->Constant(value));
|
||||
}
|
||||
|
||||
@ -621,11 +267,6 @@ Isolate* JSGlobalSpecialization::isolate() const {
|
||||
}
|
||||
|
||||
|
||||
MachineOperatorBuilder* JSGlobalSpecialization::machine() const {
|
||||
return jsgraph()->machine();
|
||||
}
|
||||
|
||||
|
||||
CommonOperatorBuilder* JSGlobalSpecialization::common() const {
|
||||
return jsgraph()->common();
|
||||
}
|
||||
|
@ -22,7 +22,6 @@ namespace compiler {
|
||||
class CommonOperatorBuilder;
|
||||
class JSGraph;
|
||||
class JSOperatorBuilder;
|
||||
class MachineOperatorBuilder;
|
||||
|
||||
|
||||
// Specializes a given JSGraph to a given GlobalObject, potentially constant
|
||||
@ -39,14 +38,13 @@ class JSGlobalSpecialization final : public AdvancedReducer {
|
||||
|
||||
JSGlobalSpecialization(Editor* editor, JSGraph* jsgraph, Flags flags,
|
||||
Handle<GlobalObject> global_object,
|
||||
CompilationDependencies* dependencies, Zone* zone);
|
||||
CompilationDependencies* dependencies);
|
||||
|
||||
Reduction Reduce(Node* node) final;
|
||||
|
||||
private:
|
||||
Reduction ReduceJSLoadGlobal(Node* node);
|
||||
Reduction ReduceJSStoreGlobal(Node* node);
|
||||
Reduction ReduceJSLoadNamed(Node* node);
|
||||
|
||||
Reduction Replace(Node* node, Node* value, Node* effect = nullptr,
|
||||
Node* control = nullptr) {
|
||||
@ -55,12 +53,6 @@ class JSGlobalSpecialization final : public AdvancedReducer {
|
||||
}
|
||||
Reduction Replace(Node* node, Handle<Object> value);
|
||||
|
||||
class PropertyAccessInfo;
|
||||
bool ComputePropertyAccessInfo(Handle<Map> map, Handle<Name> name,
|
||||
PropertyAccessInfo* access_info);
|
||||
bool ComputePropertyAccessInfos(MapHandleList const& maps, Handle<Name> name,
|
||||
ZoneVector<PropertyAccessInfo>* access_infos);
|
||||
|
||||
struct ScriptContextTableLookupResult;
|
||||
bool LookupInScriptContextTable(Handle<Name> name,
|
||||
ScriptContextTableLookupResult* result);
|
||||
@ -71,17 +63,14 @@ class JSGlobalSpecialization final : public AdvancedReducer {
|
||||
CommonOperatorBuilder* common() const;
|
||||
JSOperatorBuilder* javascript() const;
|
||||
SimplifiedOperatorBuilder* simplified() const;
|
||||
MachineOperatorBuilder* machine() const;
|
||||
Flags flags() const { return flags_; }
|
||||
Handle<GlobalObject> global_object() const { return global_object_; }
|
||||
CompilationDependencies* dependencies() const { return dependencies_; }
|
||||
Zone* zone() const { return zone_; }
|
||||
|
||||
JSGraph* const jsgraph_;
|
||||
Flags const flags_;
|
||||
Handle<GlobalObject> global_object_;
|
||||
CompilationDependencies* const dependencies_;
|
||||
Zone* const zone_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(JSGlobalSpecialization);
|
||||
};
|
||||
|
@ -11,11 +11,8 @@ namespace v8 {
|
||||
namespace internal {
|
||||
namespace compiler {
|
||||
|
||||
Node* JSGraph::ImmovableHeapConstant(Handle<HeapObject> value) {
|
||||
if (value->IsConsString()) {
|
||||
value = String::Flatten(Handle<String>::cast(value), TENURED);
|
||||
}
|
||||
return graph()->NewNode(common()->HeapConstant(value));
|
||||
Node* JSGraph::ImmovableHeapConstant(Handle<HeapObject> object) {
|
||||
return graph()->NewNode(common()->HeapConstant(object));
|
||||
}
|
||||
|
||||
|
||||
@ -81,7 +78,7 @@ Node* JSGraph::HeapConstant(Handle<HeapObject> value) {
|
||||
// TODO(titzer): We could also match against the addresses of immortable
|
||||
// immovables here, even without access to the heap, thus always
|
||||
// canonicalizing references to them.
|
||||
return ImmovableHeapConstant(value);
|
||||
return graph()->NewNode(common()->HeapConstant(value));
|
||||
}
|
||||
|
||||
|
||||
|
@ -369,8 +369,7 @@ Reduction JSInliner::ReduceJSCallFunction(Node* node,
|
||||
info.is_deoptimization_enabled()
|
||||
? JSGlobalSpecialization::kDeoptimizationEnabled
|
||||
: JSGlobalSpecialization::kNoFlags,
|
||||
handle(info.global_object(), info.isolate()), info_->dependencies(),
|
||||
local_zone_);
|
||||
handle(info.global_object(), info.isolate()), info_->dependencies());
|
||||
graph_reducer.AddReducer(&dead_code_elimination);
|
||||
graph_reducer.AddReducer(&common_reducer);
|
||||
graph_reducer.AddReducer(&global_specialization);
|
||||
|
@ -518,7 +518,7 @@ struct NativeContextSpecializationPhase {
|
||||
? JSGlobalSpecialization::kDeoptimizationEnabled
|
||||
: JSGlobalSpecialization::kNoFlags,
|
||||
handle(data->info()->global_object(), data->isolate()),
|
||||
data->info()->dependencies(), temp_zone);
|
||||
data->info()->dependencies());
|
||||
AddReducer(data, &graph_reducer, &dead_code_elimination);
|
||||
AddReducer(data, &graph_reducer, &common_reducer);
|
||||
AddReducer(data, &graph_reducer, &global_specialization);
|
||||
|
@ -19,8 +19,6 @@ class Map;
|
||||
// index it was originally generated from.
|
||||
class FieldIndex final {
|
||||
public:
|
||||
FieldIndex() : bit_field_(0) {}
|
||||
|
||||
static FieldIndex ForPropertyIndex(Map* map,
|
||||
int index,
|
||||
bool is_double = false);
|
||||
|
@ -4905,7 +4905,6 @@ bool Map::IsJSGlobalProxyMap() {
|
||||
bool Map::IsJSGlobalObjectMap() {
|
||||
return instance_type() == JS_GLOBAL_OBJECT_TYPE;
|
||||
}
|
||||
bool Map::IsJSTypedArrayMap() { return instance_type() == JS_TYPED_ARRAY_TYPE; }
|
||||
bool Map::IsGlobalObjectMap() {
|
||||
const InstanceType type = instance_type();
|
||||
return type == JS_GLOBAL_OBJECT_TYPE || type == JS_BUILTINS_OBJECT_TYPE;
|
||||
|
@ -5877,7 +5877,6 @@ class Map: public HeapObject {
|
||||
inline bool IsJSProxyMap();
|
||||
inline bool IsJSGlobalProxyMap();
|
||||
inline bool IsJSGlobalObjectMap();
|
||||
inline bool IsJSTypedArrayMap();
|
||||
inline bool IsGlobalObjectMap();
|
||||
|
||||
inline bool CanOmitMapChecks();
|
||||
|
@ -90,6 +90,7 @@ function f3(one) {
|
||||
for (var j = 0; j < 5; ++j) f3(1);
|
||||
%OptimizeFunctionOnNextCall(f3);
|
||||
f3(1);
|
||||
assertTrue(%GetOptimizationStatus(f3) != 2);
|
||||
|
||||
|
||||
|
||||
|
@ -88,6 +88,7 @@ function f3(one) {
|
||||
for (var j = 0; j < 5; ++j) f3(1);
|
||||
%OptimizeFunctionOnNextCall(f3);
|
||||
f3(1);
|
||||
assertTrue(%GetOptimizationStatus(f3) != 2);
|
||||
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user