aboutsummaryrefslogtreecommitdiff
path: root/src/compiler/js-global-object-specialization.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler/js-global-object-specialization.cc')
-rw-r--r--src/compiler/js-global-object-specialization.cc287
1 files changed, 0 insertions, 287 deletions
diff --git a/src/compiler/js-global-object-specialization.cc b/src/compiler/js-global-object-specialization.cc
deleted file mode 100644
index e9ff060d..00000000
--- a/src/compiler/js-global-object-specialization.cc
+++ /dev/null
@@ -1,287 +0,0 @@
-// Copyright 2015 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "src/compiler/js-global-object-specialization.h"
-
-#include "src/compilation-dependencies.h"
-#include "src/compiler/access-builder.h"
-#include "src/compiler/common-operator.h"
-#include "src/compiler/js-graph.h"
-#include "src/compiler/js-operator.h"
-#include "src/compiler/node-properties.h"
-#include "src/compiler/simplified-operator.h"
-#include "src/compiler/type-cache.h"
-#include "src/lookup.h"
-#include "src/objects-inl.h"
-
-namespace v8 {
-namespace internal {
-namespace compiler {
-
-struct JSGlobalObjectSpecialization::ScriptContextTableLookupResult {
- Handle<Context> context;
- bool immutable;
- int index;
-};
-
-JSGlobalObjectSpecialization::JSGlobalObjectSpecialization(
- Editor* editor, JSGraph* jsgraph, Handle<JSGlobalObject> global_object,
- CompilationDependencies* dependencies)
- : AdvancedReducer(editor),
- jsgraph_(jsgraph),
- global_object_(global_object),
- dependencies_(dependencies),
- type_cache_(TypeCache::Get()) {}
-
-Reduction JSGlobalObjectSpecialization::Reduce(Node* node) {
- switch (node->opcode()) {
- case IrOpcode::kJSLoadGlobal:
- return ReduceJSLoadGlobal(node);
- case IrOpcode::kJSStoreGlobal:
- return ReduceJSStoreGlobal(node);
- default:
- break;
- }
- return NoChange();
-}
-
-namespace {
-
-FieldAccess ForPropertyCellValue(MachineRepresentation representation,
- Type* type, Handle<Name> name) {
- WriteBarrierKind kind = kFullWriteBarrier;
- if (representation == MachineRepresentation::kTaggedSigned) {
- kind = kNoWriteBarrier;
- } else if (representation == MachineRepresentation::kTaggedPointer) {
- kind = kPointerWriteBarrier;
- }
- MachineType r = MachineType::TypeForRepresentation(representation);
- FieldAccess access = {kTaggedBase, PropertyCell::kValueOffset, name, type, r,
- kind};
- return access;
-}
-} // namespace
-
-Reduction JSGlobalObjectSpecialization::ReduceJSLoadGlobal(Node* node) {
- DCHECK_EQ(IrOpcode::kJSLoadGlobal, node->opcode());
- Handle<Name> name = LoadGlobalParametersOf(node->op()).name();
- Node* effect = NodeProperties::GetEffectInput(node);
- Node* control = NodeProperties::GetControlInput(node);
-
- // Try to lookup the name on the script context table first (lexical scoping).
- ScriptContextTableLookupResult result;
- if (LookupInScriptContextTable(name, &result)) {
- if (result.context->is_the_hole(isolate(), result.index)) return NoChange();
- Node* context = jsgraph()->HeapConstant(result.context);
- Node* value = effect = graph()->NewNode(
- javascript()->LoadContext(0, result.index, result.immutable), context,
- context, effect);
- ReplaceWithValue(node, value, effect);
- return Replace(value);
- }
-
- // Lookup on the global object instead. We only deal with own data
- // properties of the global object here (represented as PropertyCell).
- LookupIterator it(global_object(), name, LookupIterator::OWN);
- if (it.state() != LookupIterator::DATA) return NoChange();
- if (!it.GetHolder<JSObject>()->IsJSGlobalObject()) return NoChange();
- Handle<PropertyCell> property_cell = it.GetPropertyCell();
- PropertyDetails property_details = property_cell->property_details();
- Handle<Object> property_cell_value(property_cell->value(), isolate());
-
- // Load from non-configurable, read-only data property on the global
- // object can be constant-folded, even without deoptimization support.
- if (!property_details.IsConfigurable() && property_details.IsReadOnly()) {
- Node* value = jsgraph()->Constant(property_cell_value);
- ReplaceWithValue(node, value);
- return Replace(value);
- }
-
- // Record a code dependency on the cell if we can benefit from the
- // additional feedback, or the global property is configurable (i.e.
- // can be deleted or reconfigured to an accessor property).
- if (property_details.cell_type() != PropertyCellType::kMutable ||
- property_details.IsConfigurable()) {
- dependencies()->AssumePropertyCell(property_cell);
- }
-
- // Load from constant/undefined global property can be constant-folded.
- if (property_details.cell_type() == PropertyCellType::kConstant ||
- property_details.cell_type() == PropertyCellType::kUndefined) {
- Node* value = jsgraph()->Constant(property_cell_value);
- ReplaceWithValue(node, value);
- return Replace(value);
- }
-
- // Load from constant type cell can benefit from type feedback.
- Type* property_cell_value_type = Type::NonInternal();
- MachineRepresentation representation = MachineRepresentation::kTagged;
- if (property_details.cell_type() == PropertyCellType::kConstantType) {
- // Compute proper type based on the current value in the cell.
- if (property_cell_value->IsSmi()) {
- property_cell_value_type = Type::SignedSmall();
- representation = MachineRepresentation::kTaggedSigned;
- } else if (property_cell_value->IsNumber()) {
- property_cell_value_type = Type::Number();
- representation = MachineRepresentation::kTaggedPointer;
- } else {
- // TODO(turbofan): Track the property_cell_value_map on the FieldAccess
- // below and use it in LoadElimination to eliminate map checks.
- Handle<Map> property_cell_value_map(
- Handle<HeapObject>::cast(property_cell_value)->map(), isolate());
- property_cell_value_type = Type::For(property_cell_value_map);
- representation = MachineRepresentation::kTaggedPointer;
- }
- }
- Node* value = effect =
- graph()->NewNode(simplified()->LoadField(ForPropertyCellValue(
- representation, property_cell_value_type, name)),
- jsgraph()->HeapConstant(property_cell), effect, control);
- ReplaceWithValue(node, value, effect, control);
- return Replace(value);
-}
-
-
-Reduction JSGlobalObjectSpecialization::ReduceJSStoreGlobal(Node* node) {
- DCHECK_EQ(IrOpcode::kJSStoreGlobal, node->opcode());
- Handle<Name> name = StoreGlobalParametersOf(node->op()).name();
- Node* value = NodeProperties::GetValueInput(node, 0);
- Node* effect = NodeProperties::GetEffectInput(node);
- Node* control = NodeProperties::GetControlInput(node);
-
- // Try to lookup the name on the script context table first (lexical scoping).
- ScriptContextTableLookupResult result;
- if (LookupInScriptContextTable(name, &result)) {
- if (result.context->is_the_hole(isolate(), result.index)) return NoChange();
- if (result.immutable) return NoChange();
- Node* context = jsgraph()->HeapConstant(result.context);
- effect = graph()->NewNode(javascript()->StoreContext(0, result.index),
- context, value, context, effect, control);
- ReplaceWithValue(node, value, effect, control);
- return Replace(value);
- }
-
- // Lookup on the global object instead. We only deal with own data
- // properties of the global object here (represented as PropertyCell).
- LookupIterator it(global_object(), name, LookupIterator::OWN);
- if (it.state() != LookupIterator::DATA) return NoChange();
- if (!it.GetHolder<JSObject>()->IsJSGlobalObject()) return NoChange();
- Handle<PropertyCell> property_cell = it.GetPropertyCell();
- PropertyDetails property_details = property_cell->property_details();
- Handle<Object> property_cell_value(property_cell->value(), isolate());
-
- // Don't even bother trying to lower stores to read-only data properties.
- if (property_details.IsReadOnly()) return NoChange();
- switch (property_details.cell_type()) {
- case PropertyCellType::kUndefined: {
- return NoChange();
- }
- case PropertyCellType::kConstant: {
- // Record a code dependency on the cell, and just deoptimize if the new
- // value doesn't match the previous value stored inside the cell.
- dependencies()->AssumePropertyCell(property_cell);
- Node* check = graph()->NewNode(simplified()->ReferenceEqual(), value,
- jsgraph()->Constant(property_cell_value));
- effect =
- graph()->NewNode(simplified()->CheckIf(), check, effect, control);
- break;
- }
- case PropertyCellType::kConstantType: {
- // Record a code dependency on the cell, and just deoptimize if the new
- // values' type doesn't match the type of the previous value in the cell.
- dependencies()->AssumePropertyCell(property_cell);
- Type* property_cell_value_type;
- MachineRepresentation representation = MachineRepresentation::kTagged;
- if (property_cell_value->IsHeapObject()) {
- // We cannot do anything if the {property_cell_value}s map is no
- // longer stable.
- Handle<Map> property_cell_value_map(
- Handle<HeapObject>::cast(property_cell_value)->map(), isolate());
- if (!property_cell_value_map->is_stable()) return NoChange();
- dependencies()->AssumeMapStable(property_cell_value_map);
-
- // Check that the {value} is a HeapObject.
- value = effect = graph()->NewNode(simplified()->CheckHeapObject(),
- value, effect, control);
-
- // Check {value} map agains the {property_cell} map.
- effect = graph()->NewNode(
- simplified()->CheckMaps(1), value,
- jsgraph()->HeapConstant(property_cell_value_map), effect, control);
- property_cell_value_type = Type::OtherInternal();
- representation = MachineRepresentation::kTaggedPointer;
- } else {
- // Check that the {value} is a Smi.
- value = effect =
- graph()->NewNode(simplified()->CheckSmi(), value, effect, control);
- property_cell_value_type = Type::SignedSmall();
- representation = MachineRepresentation::kTaggedSigned;
- }
- effect = graph()->NewNode(
- simplified()->StoreField(ForPropertyCellValue(
- representation, property_cell_value_type, name)),
- jsgraph()->HeapConstant(property_cell), value, effect, control);
- break;
- }
- case PropertyCellType::kMutable: {
- // Store to non-configurable, data property on the global can be lowered
- // to a field store, even without recording a code dependency on the cell,
- // because the property cannot be deleted or reconfigured to an accessor
- // or interceptor property.
- if (property_details.IsConfigurable()) {
- // Protect lowering by recording a code dependency on the cell.
- dependencies()->AssumePropertyCell(property_cell);
- }
- effect = graph()->NewNode(
- simplified()->StoreField(ForPropertyCellValue(
- MachineRepresentation::kTagged, Type::NonInternal(), name)),
- jsgraph()->HeapConstant(property_cell), value, effect, control);
- break;
- }
- }
- ReplaceWithValue(node, value, effect, control);
- return Replace(value);
-}
-
-bool JSGlobalObjectSpecialization::LookupInScriptContextTable(
- Handle<Name> name, ScriptContextTableLookupResult* result) {
- if (!name->IsString()) return false;
- Handle<ScriptContextTable> script_context_table(
- global_object()->native_context()->script_context_table(), isolate());
- ScriptContextTable::LookupResult lookup_result;
- if (!ScriptContextTable::Lookup(script_context_table,
- Handle<String>::cast(name), &lookup_result)) {
- return false;
- }
- Handle<Context> script_context = ScriptContextTable::GetContext(
- script_context_table, lookup_result.context_index);
- result->context = script_context;
- result->immutable = lookup_result.mode == CONST;
- result->index = lookup_result.slot_index;
- return true;
-}
-
-Graph* JSGlobalObjectSpecialization::graph() const {
- return jsgraph()->graph();
-}
-
-Isolate* JSGlobalObjectSpecialization::isolate() const {
- return jsgraph()->isolate();
-}
-
-CommonOperatorBuilder* JSGlobalObjectSpecialization::common() const {
- return jsgraph()->common();
-}
-
-JSOperatorBuilder* JSGlobalObjectSpecialization::javascript() const {
- return jsgraph()->javascript();
-}
-
-SimplifiedOperatorBuilder* JSGlobalObjectSpecialization::simplified() const {
- return jsgraph()->simplified();
-}
-
-} // namespace compiler
-} // namespace internal
-} // namespace v8