diff options
Diffstat (limited to 'src/compiler/js-global-object-specialization.cc')
-rw-r--r-- | src/compiler/js-global-object-specialization.cc | 287 |
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 |