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); |
} |