Move more nodes to the optimizing code generator.

Review URL: http://codereview.chromium.org//8678033

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@1829 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
srdjan@google.com
2011-11-24 01:14:15 +00:00
parent d2069f9ff2
commit 35faa6aaa9
4 changed files with 169 additions and 107 deletions
+59 -106
View File
@@ -33,80 +33,28 @@ DECLARE_FLAG(bool, trace_compiler);
#define __ assembler_->
class CodeGeneratorState : public StackResource {
public:
explicit CodeGeneratorState(CodeGenerator* codegen)
: StackResource(Isolate::Current()),
codegen_(codegen),
parent_(codegen->state()) {
if (parent_ != NULL) {
root_node_ = parent_->root_node_;
loop_level_ = parent_->loop_level_;
context_level_ = parent_->context_level_;
current_try_index_ = parent_->current_try_index_;
} else {
root_node_ = NULL;
loop_level_ = 0;
context_level_ = 0;
current_try_index_ = CatchClauseNode::kInvalidTryIndex;
}
codegen_->set_state(this);
}
virtual ~CodeGeneratorState() {
codegen_->set_state(parent_);
CodeGeneratorState::CodeGeneratorState(CodeGenerator* codegen)
: StackResource(Isolate::Current()),
codegen_(codegen),
parent_(codegen->state()) {
if (parent_ != NULL) {
root_node_ = parent_->root_node_;
loop_level_ = parent_->loop_level_;
context_level_ = parent_->context_level_;
current_try_index_ = parent_->current_try_index_;
} else {
root_node_ = NULL;
loop_level_ = 0;
context_level_ = 0;
current_try_index_ = CatchClauseNode::kInvalidTryIndex;
}
codegen_->set_state(this);
}
CodeGeneratorState* parent() const { return parent_; }
AstNode* root_node() const { return root_node_; }
void set_root_node(AstNode* value) { root_node_ = value; }
bool IsRootNode(AstNode* node) const {
return root_node_ == node;
}
int loop_level() const { return loop_level_; }
void set_loop_level(int loop_level) {
loop_level_ = loop_level;
}
int context_level() const { return context_level_; }
void set_context_level(int context_level) {
context_level_ = context_level;
}
int try_index() const { return current_try_index_; }
void set_try_index(int value) {
current_try_index_ = value;
}
private:
CodeGenerator* codegen_;
CodeGeneratorState* parent_;
AstNode* root_node_;
// The loop level reflects the lexical nesting of loop statements, regardless
// of the presence of captured variables.
int loop_level_;
// The runtime context level is only incremented when a new context is
// allocated and chained to the list of contexts. This occurs when the scopes
// at the current loop level contain captured variables.
int context_level_;
// We identify each try block in this function with an unique 'try index'
// value.
// The 'try index' is used to match the try blocks with the corresponding
// catch block (if one exists). The PC descriptors generated for
// statements in the try block use this index so that it can be matched
// to the appropriate catch block.
// The 'try index' value is generated by incrementing the try_index_
// variable in the CodeGenerator object.
// We store the 'try index' of the block of code that we are
// currently generating code for in the current_try_index_ variable.
int current_try_index_;
DISALLOW_IMPLICIT_CONSTRUCTORS(CodeGeneratorState);
};
CodeGeneratorState::~CodeGeneratorState() {
codegen_->set_state(parent_);
}
class CodeGenerator::DescriptorList : public ZoneAllocated {
@@ -767,6 +715,45 @@ void CodeGenerator::GenerateEntryCode() {
}
void CodeGenerator::GenerateReturnEpilog() {
// Unchain the context(s) up to context level 0.
int context_level = state()->context_level();
ASSERT(context_level >= 0);
while (context_level-- > 0) {
__ movl(CTX, FieldAddress(CTX, Context::parent_offset()));
}
#ifdef DEBUG
// Check that the entry stack size matches the exit stack size.
__ movl(EDX, EBP);
__ subl(EDX, ESP);
ASSERT(locals_space_size() >= 0);
__ cmpl(EDX, Immediate(locals_space_size()));
Label wrong_stack;
__ j(NOT_EQUAL, &wrong_stack, Assembler::kNearJump);
#endif // DEBUG.
if (FLAG_trace_functions) {
__ pushl(EAX); // Preserve result.
const Function& function =
Function::ZoneHandle(parsed_function_.function().raw());
__ LoadObject(EBX, function);
__ pushl(EBX);
GenerateCallRuntime(AstNode::kNoId,
0,
kTraceFunctionExitRuntimeEntry);
__ popl(EAX); // Remove argument.
__ popl(EAX); // Restore result.
}
__ LeaveFrame();
__ ret();
#ifdef DEBUG
__ Bind(&wrong_stack);
__ Stop("Exit stack size does not match the entry stack size.");
#endif // DEBUG.
}
void CodeGenerator::VisitReturnNode(ReturnNode* node) {
ASSERT(!IsResultNeeded(node));
ASSERT(node->value() != NULL);
@@ -808,41 +795,7 @@ void CodeGenerator::VisitReturnNode(ReturnNode* node) {
String::ZoneHandle(String::NewSymbol("function result")));
}
}
// Unchain the context(s) up to context level 0.
int context_level = state()->context_level();
ASSERT(context_level >= 0);
while (context_level-- > 0) {
__ movl(CTX, FieldAddress(CTX, Context::parent_offset()));
}
#ifdef DEBUG
// Check that the entry stack size matches the exit stack size.
__ movl(EDX, EBP);
__ subl(EDX, ESP);
ASSERT(locals_space_size() >= 0);
__ cmpl(EDX, Immediate(locals_space_size()));
Label wrong_stack;
__ j(NOT_EQUAL, &wrong_stack, Assembler::kNearJump);
#endif // DEBUG.
if (FLAG_trace_functions) {
__ pushl(EAX); // Preserve result.
const Function& function =
Function::ZoneHandle(parsed_function_.function().raw());
__ LoadObject(EBX, function);
__ pushl(EBX);
GenerateCallRuntime(AstNode::kNoId,
0,
kTraceFunctionExitRuntimeEntry);
__ popl(EAX); // Remove argument.
__ popl(EAX); // Restore result.
}
__ LeaveFrame();
__ ret();
#ifdef DEBUG
__ Bind(&wrong_stack);
__ Stop("Exit stack size does not match the entry stack size.");
#endif // DEBUG.
GenerateReturnEpilog();
}
+62 -1
View File
@@ -19,9 +19,68 @@ namespace dart {
// Forward Declarations.
class Assembler;
class AstNode;
class CodeGeneratorState;
class CodeGenerator;
class SourceLabel;
class CodeGeneratorState : public StackResource {
public:
explicit CodeGeneratorState(CodeGenerator* codegen);
virtual ~CodeGeneratorState();
CodeGeneratorState* parent() const { return parent_; }
AstNode* root_node() const { return root_node_; }
void set_root_node(AstNode* value) { root_node_ = value; }
bool IsRootNode(AstNode* node) const {
return root_node_ == node;
}
int loop_level() const { return loop_level_; }
void set_loop_level(int loop_level) {
loop_level_ = loop_level;
}
int context_level() const { return context_level_; }
void set_context_level(int context_level) {
context_level_ = context_level;
}
int try_index() const { return current_try_index_; }
void set_try_index(int value) {
current_try_index_ = value;
}
private:
CodeGenerator* codegen_;
CodeGeneratorState* parent_;
AstNode* root_node_;
// The loop level reflects the lexical nesting of loop statements, regardless
// of the presence of captured variables.
int loop_level_;
// The runtime context level is only incremented when a new context is
// allocated and chained to the list of contexts. This occurs when the scopes
// at the current loop level contain captured variables.
int context_level_;
// We identify each try block in this function with an unique 'try index'
// value.
// The 'try index' is used to match the try blocks with the corresponding
// catch block (if one exists). The PC descriptors generated for
// statements in the try block use this index so that it can be matched
// to the appropriate catch block.
// The 'try index' value is generated by incrementing the try_index_
// variable in the CodeGenerator object.
// We store the 'try index' of the block of code that we are
// currently generating code for in the current_try_index_ variable.
int current_try_index_;
DISALLOW_IMPLICIT_CONSTRUCTORS(CodeGeneratorState);
};
class CodeGenerator : public AstNodeVisitor {
public:
CodeGenerator(Assembler* assembler, const ParsedFunction& parsed_function);
@@ -63,6 +122,8 @@ NODE_LIST(DEFINE_VISITOR_FUNCTION)
virtual void CountBackwardLoop();
void GenerateReturnEpilog();
private:
// TODO(srdjan): Remove the friendship once the two compilers are properly
// structured.
+45
View File
@@ -2554,6 +2554,51 @@ void OptimizingCodeGenerator::VisitStaticCallNode(StaticCallNode* node) {
}
}
void OptimizingCodeGenerator::VisitReturnNode(ReturnNode* node) {
if ((node->inlined_finally_list_length() > 0) || FLAG_enable_type_checks) {
CodeGenerator::VisitReturnNode(node);
return;
}
ASSERT(!IsResultNeeded(node));
ASSERT(node->value() != NULL);
VisitLoadOne(node->value(), EAX);
GenerateReturnEpilog();
}
void OptimizingCodeGenerator::VisitSequenceNode(SequenceNode* node_sequence) {
if (FLAG_enable_type_checks ||
(node_sequence->scope()->num_context_variables() > 0)) {
CodeGenerator::VisitSequenceNode(node_sequence);
return;
}
for (int i = 0; i < node_sequence->length(); i++) {
AstNode* child_node = node_sequence->NodeAt(i);
state()->set_root_node(child_node);
child_node->Visit(this);
}
if (node_sequence->label() != NULL) {
__ Bind(node_sequence->label()->break_label());
}
}
void OptimizingCodeGenerator::VisitStoreInstanceFieldNode(
StoreInstanceFieldNode* node) {
if (FLAG_enable_type_checks) {
CodeGenerator::VisitStoreInstanceFieldNode(node);
return;
}
VisitLoadTwo(node->instance(), node->value(), EDX, EAX);
__ StoreIntoObject(EDX, FieldAddress(EDX, node->field().Offset()), EAX);
if (IsResultNeeded(node)) {
// The result is the input value.
__ pushl(EAX);
}
}
} // namespace dart
#endif // defined TARGET_ARCH_IA32
+3
View File
@@ -40,6 +40,9 @@ class OptimizingCodeGenerator : public CodeGenerator {
virtual void VisitIfNode(IfNode* node);
virtual void VisitInstanceCallNode(InstanceCallNode* node);
virtual void VisitStaticCallNode(StaticCallNode* node);
virtual void VisitReturnNode(ReturnNode* node);
virtual void VisitSequenceNode(SequenceNode* node_sequence);
virtual void VisitStoreInstanceFieldNode(StoreInstanceFieldNode* node);
// Return true if intrinsification succeeded and no more code is needed.
// Returns false if either no intrinsification occured or if intrinsified