| Index: src/compiler/js-type-feedback.cc | 
| diff --git a/src/compiler/js-type-feedback.cc b/src/compiler/js-type-feedback.cc | 
| index fa5e33f840e107e8acbedd472c446d5ad826c41c..749eebab290919e9fc5338a9734f62ca72dfb49e 100644 | 
| --- a/src/compiler/js-type-feedback.cc | 
| +++ b/src/compiler/js-type-feedback.cc | 
| @@ -8,6 +8,7 @@ | 
|  | 
| #include "src/accessors.h" | 
| #include "src/ast.h" | 
| +#include "src/compiler.h" | 
| #include "src/type-info.h" | 
|  | 
| #include "src/compiler/access-builder.h" | 
| @@ -78,6 +79,18 @@ Reduction JSTypeFeedbackSpecializer::Reduce(Node* node) { | 
| } | 
|  | 
|  | 
| +static void AddFieldAccessTypes(FieldAccess* access, | 
| +                                PropertyDetails property_details) { | 
| +  if (property_details.representation().IsSmi()) { | 
| +    access->type = Type::SignedSmall(); | 
| +    access->machine_type = static_cast<MachineType>(kTypeInt32 | kRepTagged); | 
| +  } else if (property_details.representation().IsDouble()) { | 
| +    access->type = Type::Number(); | 
| +    access->machine_type = kMachFloat64; | 
| +  } | 
| +} | 
| + | 
| + | 
| static bool GetInObjectFieldAccess(LoadOrStore mode, Handle<Map> map, | 
| Handle<Name> name, FieldAccess* access) { | 
| access->base_is_tagged = kTaggedBase; | 
| @@ -109,26 +122,18 @@ static bool GetInObjectFieldAccess(LoadOrStore mode, Handle<Map> map, | 
| return false; | 
| } | 
|  | 
| +  // Transfer known types from property details. | 
| +  AddFieldAccessTypes(access, property_details); | 
| + | 
| if (mode == STORE) { | 
| -    if (property_details.IsReadOnly()) return false; | 
| -    if (is_smi) { | 
| -      // TODO(turbofan): SMI stores. | 
| +    if (property_details.IsReadOnly()) { | 
| +      // TODO(turbofan): deopt, ignore or throw on readonly stores. | 
| return false; | 
| } | 
| -    if (is_double) { | 
| -      // TODO(turbofan): double stores. | 
| +    if (is_smi || is_double) { | 
| +      // TODO(turbofan): check type and deopt for SMI/double stores. | 
| return false; | 
| } | 
| -  } else { | 
| -    // Check property details for loads. | 
| -    if (is_smi) { | 
| -      access->type = Type::SignedSmall(); | 
| -      access->machine_type = static_cast<MachineType>(kTypeInt32 | kRepTagged); | 
| -    } | 
| -    if (is_double) { | 
| -      access->type = Type::Number(); | 
| -      access->machine_type = kMachFloat64; | 
| -    } | 
| } | 
|  | 
| int index = map->instance_descriptors()->GetFieldIndex(number); | 
| @@ -144,8 +149,20 @@ static bool GetInObjectFieldAccess(LoadOrStore mode, Handle<Map> map, | 
| } | 
|  | 
|  | 
| +static bool IsGlobalObject(Node* node) { | 
| +  return NodeProperties::IsTyped(node) && | 
| +         NodeProperties::GetBounds(node).upper->Is(Type::GlobalObject()); | 
| +} | 
| + | 
| + | 
| Reduction JSTypeFeedbackSpecializer::ReduceJSLoadNamed(Node* node) { | 
| DCHECK(node->opcode() == IrOpcode::kJSLoadNamed); | 
| +  Node* receiver = node->InputAt(0); | 
| +  if (IsGlobalObject(receiver)) { | 
| +    return ReduceJSLoadNamedForGlobalVariable(node); | 
| +  } | 
| + | 
| +  if (!FLAG_turbo_deoptimization) return NoChange(); | 
| // TODO(titzer): deopt locations are wrong for property accesses | 
| if (!EAGER_DEOPT_LOCATIONS_FOR_PROPERTY_ACCESS_ARE_CORRECT) return NoChange(); | 
|  | 
| @@ -158,7 +175,6 @@ Reduction JSTypeFeedbackSpecializer::ReduceJSLoadNamed(Node* node) { | 
| const LoadNamedParameters& p = LoadNamedParametersOf(node->op()); | 
| SmallMapList maps; | 
| Handle<Name> name = p.name().handle(); | 
| -  Node* receiver = node->InputAt(0); | 
| Node* effect = NodeProperties::GetEffectInput(node); | 
| GatherReceiverTypes(receiver, effect, id, name, &maps); | 
|  | 
| @@ -191,6 +207,74 @@ Reduction JSTypeFeedbackSpecializer::ReduceJSLoadNamed(Node* node) { | 
| } | 
|  | 
|  | 
| +Reduction JSTypeFeedbackSpecializer::ReduceJSLoadNamedForGlobalVariable( | 
| +    Node* node) { | 
| +  Handle<String> name = | 
| +      Handle<String>::cast(LoadNamedParametersOf(node->op()).name().handle()); | 
| +  // Try to optimize loads from the global object. | 
| +  Handle<Object> constant_value = | 
| +      jsgraph()->isolate()->factory()->GlobalConstantFor(name); | 
| +  if (!constant_value.is_null()) { | 
| +    // Always optimize global constants. | 
| +    Node* constant = jsgraph()->Constant(constant_value); | 
| +    NodeProperties::ReplaceWithValue(node, constant); | 
| +    return Replace(constant); | 
| +  } | 
| + | 
| +  if (global_object_.is_null()) { | 
| +    // Nothing else can be done if we don't have a global object. | 
| +    return NoChange(); | 
| +  } | 
| + | 
| +  if (FLAG_turbo_deoptimization) { | 
| +    // Handle lookups in the script context. | 
| +    { | 
| +      Handle<ScriptContextTable> script_contexts( | 
| +          global_object_->native_context()->script_context_table()); | 
| +      ScriptContextTable::LookupResult lookup; | 
| +      if (ScriptContextTable::Lookup(script_contexts, name, &lookup)) { | 
| +        // TODO(turbofan): introduce a LoadContext here. | 
| +        return NoChange(); | 
| +      } | 
| +    } | 
| + | 
| +    // Constant promotion or cell access requires lazy deoptimization support. | 
| +    LookupIterator it(global_object_, name, LookupIterator::OWN); | 
| + | 
| +    if (it.state() == LookupIterator::DATA) { | 
| +      Handle<PropertyCell> cell = it.GetPropertyCell(); | 
| +      dependencies_->AssumePropertyCell(cell); | 
| + | 
| +      if (it.property_details().cell_type() == PropertyCellType::kConstant) { | 
| +        // Constant promote the global's current value. | 
| +        Handle<Object> constant_value(cell->value(), jsgraph()->isolate()); | 
| +        if (constant_value->IsConsString()) { | 
| +          constant_value = | 
| +              String::Flatten(Handle<String>::cast(constant_value)); | 
| +        } | 
| +        Node* constant = jsgraph()->Constant(constant_value); | 
| +        NodeProperties::ReplaceWithValue(node, constant); | 
| +        return Replace(constant); | 
| +      } else { | 
| +        // Load directly from the property cell. | 
| +        FieldAccess access = AccessBuilder::ForPropertyCellValue(); | 
| +        Node* control = NodeProperties::GetControlInput(node); | 
| +        Node* load_field = graph()->NewNode( | 
| +            simplified()->LoadField(access), jsgraph()->Constant(cell), | 
| +            NodeProperties::GetEffectInput(node), control); | 
| +        NodeProperties::ReplaceWithValue(node, load_field, load_field, control); | 
| +        return Replace(load_field); | 
| +      } | 
| +    } | 
| +  } else { | 
| +    // TODO(turbofan): non-configurable properties on the global object | 
| +    // should be loadable through a cell without deoptimization support. | 
| +  } | 
| + | 
| +  return NoChange(); | 
| +} | 
| + | 
| + | 
| Reduction JSTypeFeedbackSpecializer::ReduceJSLoadProperty(Node* node) { | 
| return NoChange(); | 
| } | 
|  |