Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(836)

Unified Diff: runtime/vm/flow_graph_compiler_x64.cc

Issue 9464009: Add enough compiler support to compile empty functions on x64. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Include file inadvertently left out. Created 8 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: runtime/vm/flow_graph_compiler_x64.cc
diff --git a/runtime/vm/flow_graph_compiler_x64.cc b/runtime/vm/flow_graph_compiler_x64.cc
new file mode 100644
index 0000000000000000000000000000000000000000..9d790c0cc9c1412f4ef96a2536b80e987635d96c
--- /dev/null
+++ b/runtime/vm/flow_graph_compiler_x64.cc
@@ -0,0 +1,227 @@
+// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include "vm/globals.h" // Needed here to get TARGET_ARCH_X64.
+#if defined(TARGET_ARCH_X64)
+
+#include "vm/flow_graph_compiler.h"
+
+#include "vm/ast_printer.h"
+#include "vm/code_generator.h"
+#include "vm/disassembler.h"
+#include "vm/longjump.h"
+#include "vm/parser.h"
+#include "vm/stub_code.h"
+
+namespace dart {
+
+DECLARE_FLAG(bool, print_ast);
+DECLARE_FLAG(bool, print_scopes);
+DECLARE_FLAG(bool, trace_functions);
+DECLARE_FLAG(bool, disassemble);
+
+void FlowGraphCompiler::Bailout(const char* reason) {
+ const char* kFormat = "FlowGraphCompiler Bailout: %s.";
+ intptr_t len = OS::SNPrint(NULL, 0, kFormat, reason) + 1;
+ char* chars = reinterpret_cast<char*>(
+ Isolate::Current()->current_zone()->Allocate(len));
+ OS::SNPrint(chars, len, kFormat, reason);
+ const Error& error = Error::Handle(
+ LanguageError::New(String::Handle(String::New(chars))));
+ Isolate::Current()->long_jump_base()->Jump(1, error);
+}
+
+
+#define __ assembler_->
+
+void FlowGraphCompiler::CompileValue(Value* value) {
+ if (value->IsConstant()) {
+ ConstantValue* constant = value->AsConstant();
+ if (constant->instance().IsSmi()) {
+ int64_t imm = reinterpret_cast<int64_t>(constant->instance().raw());
+ __ movq(RAX, Immediate(imm));
+ } else {
+ __ LoadObject(RAX, value->AsConstant()->instance());
+ }
+ } else {
+ ASSERT(value->IsTemp());
+ Bailout("return of non-ConstantValue value");
+ }
+}
+
+
+void FlowGraphCompiler::VisitJoinEntry(JoinEntryInstr* instr) {
+ Bailout("JoinEntryInstr");
+}
+
+
+void FlowGraphCompiler::VisitTargetEntry(TargetEntryInstr* instr) {
+ // Since we don't handle branching control flow yet, there is nothing to do.
+}
+
+
+void FlowGraphCompiler::VisitDo(DoInstr* instr) {
+ Bailout("DoInstr");
+}
+
+
+void FlowGraphCompiler::VisitBind(BindInstr* instr) {
+ Bailout("DoInstr");
+}
+
+
+void FlowGraphCompiler::VisitReturn(ReturnInstr* instr) {
+ CompileValue(instr->value());
+
+#ifdef DEBUG
+ // Check that the entry stack size matches the exit stack size.
+ const intptr_t locals_space_size = 0;
+ __ movq(R10, RBP);
+ __ subq(R10, RSP);
+ __ cmpq(R10, Immediate(locals_space_size));
+ Label stack_ok;
+ __ j(EQUAL, &stack_ok, Assembler::kNearJump);
+ __ Stop("Exit stack size does not match the entry stack size.");
+ __ Bind(&stack_ok);
+#endif // DEBUG.
+
+ if (FLAG_trace_functions) {
+ __ pushq(RAX); // Preserve result.
+ const Function& function =
+ Function::ZoneHandle(parsed_function_.function().raw());
+ __ LoadObject(RBX, function);
+ __ pushq(RBX);
+ GenerateCallRuntime(AstNode::kNoId,
+ 0,
+ kTraceFunctionExitRuntimeEntry);
+ __ popq(RAX); // Remove argument.
+ __ popq(RAX); // Restore result.
+ }
+ __ LeaveFrame();
+ __ ret();
+}
+
+
+void FlowGraphCompiler::VisitBranch(BranchInstr* instr) {
+ Bailout("VisitBranch");
+}
+
+
+void FlowGraphCompiler::CompileGraph() {
+ const Function& function = parsed_function_.function();
+ if ((function.num_fixed_parameters() != 0) ||
+ (function.num_optional_parameters() != 0)) {
+ Bailout("function has parameters");
+ }
+ LocalScope* scope = parsed_function_.node_sequence()->scope();
+ if (scope->child() != NULL) {
+ Bailout("function has local scopes");
+ }
+ LocalScope* context_owner = NULL;
+ const int first_parameter_index = 1;
+ const int parameter_count = 0;
+ const int first_local_index = -1;
+ int first_free_frame_index =
+ scope->AllocateVariables(first_parameter_index,
+ parameter_count,
+ first_local_index,
+ scope,
+ &context_owner);
+ const int local_count = first_local_index - first_free_frame_index;
+ if (local_count != 0) Bailout("function has locals");
+
+ if (blocks_->length() != 1) Bailout("more than 1 basic block");
+
+ // Specialized version of entry code from CodeGenerator::GenerateEntryCode.
+ __ EnterFrame(0);
+#ifdef DEBUG
+ const bool check_arguments = true;
+#else
+ const bool check_arguments = function.IsClosureFunction();
+#endif
+ if (check_arguments) {
+ // Check that num_fixed <= argc <= num_params.
+ Label argc_in_range;
+ // Total number of args is the first Smi in args descriptor array (R10).
+ __ movq(RAX, FieldAddress(R10, Array::data_offset()));
+ __ cmpq(RAX, Immediate(Smi::RawValue(0)));
+ __ j(EQUAL, &argc_in_range, Assembler::kNearJump);
+ if (function.IsClosureFunction()) {
+ GenerateCallRuntime(AstNode::kNoId,
+ function.token_index(),
+ kClosureArgumentMismatchRuntimeEntry);
+ } else {
+ __ Stop("Wrong number of arguments");
+ }
+ __ Bind(&argc_in_range);
+ }
+ // Generate stack overflow check.
+ __ movq(TMP, Immediate(Isolate::Current()->stack_limit_address()));
+ __ cmpq(RSP, Address(TMP, 0));
+ Label no_stack_overflow;
+ __ j(ABOVE, &no_stack_overflow);
+ GenerateCallRuntime(AstNode::kNoId,
+ function.token_index(),
+ kStackOverflowRuntimeEntry);
+ __ Bind(&no_stack_overflow);
+
+ if (FLAG_print_scopes) {
+ // Print the function scope (again) after generating the prologue in order
+ // to see annotations such as allocation indices of locals.
+ if (FLAG_print_ast) {
+ // Second printing.
+ OS::Print("Annotated ");
+ }
+ AstPrinter::PrintFunctionScope(parsed_function_);
+ }
+
+ VisitBlocks(*blocks_);
+
+ __ int3();
+ // Emit function patching code. This will be swapped with the first 13 bytes
+ // at entry point.
+ pc_descriptors_list_->AddDescriptor(PcDescriptors::kPatchCode,
+ assembler_->CodeSize(),
+ AstNode::kNoId,
+ 0,
+ -1);
+ __ jmp(&StubCode::FixCallersTargetLabel());
+
+ if (FLAG_disassemble) {
+ const char* function_fullname = function.ToFullyQualifiedCString();
+ OS::Print(";;; Function %s\n", function_fullname);
+ const Code& code = Code::Handle(Code::FinalizeCode("GRAPH", assembler_));
+ const Instructions& instructions =
+ Instructions::Handle(code.instructions());
+ uword start = instructions.EntryPoint();
+ Disassembler::Disassemble(start, start + assembler_->CodeSize());
+ OS::Print("\n");
+ }
+}
+
+
+// Infrastructure copied from class CodeGenerator.
+void FlowGraphCompiler::GenerateCallRuntime(intptr_t node_id,
+ intptr_t token_index,
+ const RuntimeEntry& entry) {
+ __ CallRuntimeFromDart(entry);
+ AddCurrentDescriptor(PcDescriptors::kOther, node_id, token_index);
+}
+
+
+// Uses current pc position and try-index.
+void FlowGraphCompiler::AddCurrentDescriptor(PcDescriptors::Kind kind,
+ intptr_t node_id,
+ intptr_t token_index) {
+ pc_descriptors_list_->AddDescriptor(kind,
+ assembler_->CodeSize(),
+ node_id,
+ token_index,
+ CatchClauseNode::kInvalidTryIndex);
+}
+
+
+} // namespace dart
+
+#endif // defined TARGET_ARCH_X64

Powered by Google App Engine
This is Rietveld 408576698