Chromium Code Reviews| Index: src/compiler/bytecode-graph-builder.cc |
| diff --git a/src/compiler/bytecode-graph-builder.cc b/src/compiler/bytecode-graph-builder.cc |
| index 5c81906a7e19bd664442c2e6e93a25902c03b8b9..18e1b42191bd92ebfecc0329367ef9ea23a677d8 100644 |
| --- a/src/compiler/bytecode-graph-builder.cc |
| +++ b/src/compiler/bytecode-graph-builder.cc |
| @@ -98,6 +98,42 @@ void BytecodeGraphBuilder::Environment::MarkAsUnreachable() { |
| } |
| +class BytecodeGraphBuilder::FrameStateBeforeAndAfter { |
| + public: |
| + explicit FrameStateBeforeAndAfter(BytecodeGraphBuilder* builder) |
| + : builder_(builder) { |
| + // TODO(mythria): Replace with the actual frame state. Current |
| + // implementation introduces empty frame state. |
| + frame_state_before_ = builder_->jsgraph()->EmptyFrameState(); |
| + } |
| + |
| + void AddToNode(Node* node) { |
| + int count = OperatorProperties::GetFrameStateInputCount(node->op()); |
| + DCHECK_LE(count, 2); |
| + if (count >= 1) { |
| + // Add the frame state for after the operation. |
| + DCHECK_EQ(IrOpcode::kDead, |
| + NodeProperties::GetFrameStateInput(node, 0)->opcode()); |
| + |
| + // TODO(mythria): Replace with the actual frame state. Current |
| + // implementation introduces empty frame state. |
| + NodeProperties::ReplaceFrameStateInput( |
| + node, 0, builder_->jsgraph()->EmptyFrameState()); |
| + } |
| + if (count >= 2) { |
| + // Add the frame state for before the operation. |
| + DCHECK_EQ(IrOpcode::kDead, |
| + NodeProperties::GetFrameStateInput(node, 1)->opcode()); |
| + NodeProperties::ReplaceFrameStateInput(node, 1, frame_state_before_); |
| + } |
| + } |
| + |
| + private: |
| + BytecodeGraphBuilder* builder_; |
| + Node* frame_state_before_; |
| +}; |
| + |
| + |
| BytecodeGraphBuilder::BytecodeGraphBuilder(Zone* local_zone, |
| CompilationInfo* compilation_info, |
| JSGraph* jsgraph) |
| @@ -123,6 +159,64 @@ Node* BytecodeGraphBuilder::GetFunctionContext() { |
| } |
| +Node* BytecodeGraphBuilder::GetFunctionClosure() { |
| + if (!function_closure_.is_set()) { |
| + const Operator* op = common()->Parameter( |
| + Linkage::kJSFunctionCallClosureParamIndex, "%closure"); |
| + Node* node = NewNode(op, graph()->start()); |
| + function_closure_.set(node); |
| + } |
| + return function_closure_.get(); |
| +} |
| + |
| + |
| +Node* BytecodeGraphBuilder::BuildLoadImmutableObjectField(Node* object, |
| + int offset) { |
| + return graph()->NewNode(jsgraph()->machine()->Load(kMachAnyTagged), object, |
| + jsgraph()->IntPtrConstant(offset - kHeapObjectTag), |
| + graph()->start(), graph()->start()); |
| +} |
| + |
| + |
| +Node* BytecodeGraphBuilder::BuildLoadFeedbackVector() { |
| + if (!feedback_vector_.is_set()) { |
| + Node* closure = GetFunctionClosure(); |
| + Node* shared = BuildLoadImmutableObjectField( |
| + closure, JSFunction::kSharedFunctionInfoOffset); |
| + Node* vector = BuildLoadImmutableObjectField( |
| + shared, SharedFunctionInfo::kFeedbackVectorOffset); |
| + feedback_vector_.set(vector); |
| + } |
| + return feedback_vector_.get(); |
| +} |
| + |
| + |
| +VectorSlotPair BytecodeGraphBuilder::CreateVectorSlotPair(int slot_id) { |
| + FeedbackVectorSlot slot = info()->feedback_vector()->ToSlot(slot_id); |
| + return CreateVectorSlotPair(slot); |
| +} |
| + |
| + |
| +VectorSlotPair BytecodeGraphBuilder::CreateVectorSlotPair( |
|
rmcilroy
2015/11/09 15:23:00
Just inline this into the function above (I don't
mythria
2015/11/10 09:55:35
Done.
|
| + FeedbackVectorSlot slot) { |
| + return VectorSlotPair(handle(info()->shared_info()->feedback_vector()), slot); |
| +} |
| + |
| + |
| +// TODO(mythria): This implementation introduces empty frame state. Replace with |
|
rmcilroy
2015/11/09 15:23:00
nit - /empty frame state/an empty frame state/
mythria
2015/11/10 09:55:35
Done.
|
| +// the correct frame state. |
| +void BytecodeGraphBuilder::PrepareFrameState(Node* node) { |
|
rmcilroy
2015/11/09 15:23:00
Unused? If so, please remove for now.
mythria
2015/11/10 09:55:35
Done.
|
| + int count = OperatorProperties::GetFrameStateInputCount(node->op()); |
| + if (count > 0) { |
| + DCHECK_EQ(1, count); |
| + DCHECK_EQ(IrOpcode::kDead, |
| + NodeProperties::GetFrameStateInput(node, 0)->opcode()); |
| + NodeProperties::ReplaceFrameStateInput(node, 0, |
| + jsgraph()->EmptyFrameState()); |
| + } |
| +} |
| + |
| + |
| bool BytecodeGraphBuilder::CreateGraph(bool stack_check) { |
| // Set up the basic structure of the graph. Outputs for {Start} are |
| // the formal parameters (including the receiver) plus context and |
| @@ -315,15 +409,32 @@ void BytecodeGraphBuilder::VisitStaContextSlot( |
| } |
| +void BytecodeGraphBuilder::BuildNamedLoad( |
| + const interpreter::BytecodeArrayIterator& iterator) { |
| + FrameStateBeforeAndAfter states(this); |
| + Node* object = environment()->LookupRegister(iterator.GetRegisterOperand(0)); |
| + Handle<Name> name = |
| + Handle<Name>::cast(iterator.GetConstantForIndexOperand(1)); |
| + VectorSlotPair feedback = CreateVectorSlotPair(iterator.GetIndexOperand(2)); |
| + |
| + const Operator* op = javascript()->LoadNamed(language_mode(), name, feedback); |
| + Node* node = NewNode(op, object, BuildLoadFeedbackVector()); |
| + states.AddToNode(node); |
| + environment()->BindAccumulator(node); |
| +} |
| + |
| + |
| void BytecodeGraphBuilder::VisitLoadICSloppy( |
| const interpreter::BytecodeArrayIterator& iterator) { |
| - UNIMPLEMENTED(); |
| + DCHECK(is_sloppy(language_mode())); |
| + BuildNamedLoad(iterator); |
| } |
| void BytecodeGraphBuilder::VisitLoadICStrict( |
| const interpreter::BytecodeArrayIterator& iterator) { |
| - UNIMPLEMENTED(); |
| + DCHECK(is_strict(language_mode())); |
| + BuildNamedLoad(iterator); |
| } |
| @@ -341,13 +452,15 @@ void BytecodeGraphBuilder::VisitKeyedLoadICStrict( |
| void BytecodeGraphBuilder::VisitLoadICSloppyWide( |
| const interpreter::BytecodeArrayIterator& iterator) { |
| - UNIMPLEMENTED(); |
| + DCHECK(is_sloppy(language_mode())); |
| + BuildNamedLoad(iterator); |
| } |
| void BytecodeGraphBuilder::VisitLoadICStrictWide( |
| const interpreter::BytecodeArrayIterator& iterator) { |
| - UNIMPLEMENTED(); |
| + DCHECK(is_strict(language_mode())); |
| + BuildNamedLoad(iterator); |
| } |