| Index: src/compiler/bytecode-graph-builder.cc
|
| diff --git a/src/compiler/bytecode-graph-builder.cc b/src/compiler/bytecode-graph-builder.cc
|
| index f0ec76a7b94680db72af98f2f986d08e50e1ad88..634085b8ef8ccd42144a83c4c48ab720618cdf38 100644
|
| --- a/src/compiler/bytecode-graph-builder.cc
|
| +++ b/src/compiler/bytecode-graph-builder.cc
|
| @@ -889,9 +889,59 @@ void BytecodeGraphBuilder::VisitLdaLookupSlotInsideTypeof() {
|
| }
|
|
|
| void BytecodeGraphBuilder::BuildLdaLookupContextSlot(TypeofMode typeof_mode) {
|
| - // TODO(leszeks): Build the fast path here.
|
| + uint32_t depth = bytecode_iterator().GetUnsignedImmediateOperand(2);
|
| +
|
| + // Check if any context in the depth has an extension.
|
| + Environment* slow_environment = nullptr;
|
| +
|
| + // We only need to check up to the last-but-one depth, because the an eval in
|
| + // the same scope as the variable itself has no way of shadowing it.
|
| + for (uint32_t d = 0; d < depth; d++) {
|
| + Node* extension_slot =
|
| + NewNode(javascript()->LoadContext(d, Context::EXTENSION_INDEX, false),
|
| + environment()->Context());
|
| +
|
| + Node* check_no_extension =
|
| + NewNode(javascript()->StrictEqual(CompareOperationHint::kAny),
|
| + extension_slot, jsgraph()->TheHoleConstant());
|
| +
|
| + NewBranch(check_no_extension);
|
| + Environment* false_environment = environment();
|
| + Environment* true_environment = environment()->CopyForConditional();
|
| +
|
| + {
|
| + set_environment(false_environment);
|
| + NewIfFalse();
|
| + // If there is an extension, merge into the slow path.
|
| + if (slow_environment == nullptr) {
|
| + slow_environment = false_environment;
|
| + NewMerge();
|
| + } else {
|
| + slow_environment->Merge(false_environment);
|
| + }
|
| + }
|
| +
|
| + {
|
| + set_environment(true_environment);
|
| + NewIfTrue();
|
| + // Do nothing on if there is no extension, eventually falling through to
|
| + // the fast path.
|
| + }
|
| + }
|
| +
|
| + // Fast path, do a context load.
|
| + {
|
| + uint32_t slot_index = bytecode_iterator().GetIndexOperand(1);
|
| +
|
| + const Operator* op = javascript()->LoadContext(depth, slot_index, false);
|
| + Node* context = environment()->Context();
|
| + environment()->BindAccumulator(NewNode(op, context));
|
| + NewMerge();
|
| + }
|
| + Environment* fast_environment = environment();
|
|
|
| // Slow path, do a runtime load lookup.
|
| + set_environment(slow_environment);
|
| {
|
| FrameStateBeforeAndAfter states(this);
|
|
|
| @@ -905,6 +955,9 @@ void BytecodeGraphBuilder::BuildLdaLookupContextSlot(TypeofMode typeof_mode) {
|
| Node* value = NewNode(op, name);
|
| environment()->BindAccumulator(value, &states);
|
| }
|
| +
|
| + fast_environment->Merge(slow_environment);
|
| + set_environment(fast_environment);
|
| }
|
|
|
| void BytecodeGraphBuilder::VisitLdaLookupContextSlot() {
|
|
|