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

Side by Side 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4
5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64.
6 #if defined(TARGET_ARCH_X64)
7
8 #include "vm/flow_graph_compiler.h"
9
10 #include "vm/ast_printer.h"
11 #include "vm/code_generator.h"
12 #include "vm/disassembler.h"
13 #include "vm/longjump.h"
14 #include "vm/parser.h"
15 #include "vm/stub_code.h"
16
17 namespace dart {
18
19 DECLARE_FLAG(bool, print_ast);
20 DECLARE_FLAG(bool, print_scopes);
21 DECLARE_FLAG(bool, trace_functions);
22 DECLARE_FLAG(bool, disassemble);
23
24 void FlowGraphCompiler::Bailout(const char* reason) {
25 const char* kFormat = "FlowGraphCompiler Bailout: %s.";
26 intptr_t len = OS::SNPrint(NULL, 0, kFormat, reason) + 1;
27 char* chars = reinterpret_cast<char*>(
28 Isolate::Current()->current_zone()->Allocate(len));
29 OS::SNPrint(chars, len, kFormat, reason);
30 const Error& error = Error::Handle(
31 LanguageError::New(String::Handle(String::New(chars))));
32 Isolate::Current()->long_jump_base()->Jump(1, error);
33 }
34
35
36 #define __ assembler_->
37
38 void FlowGraphCompiler::CompileValue(Value* value) {
39 if (value->IsConstant()) {
40 ConstantValue* constant = value->AsConstant();
41 if (constant->instance().IsSmi()) {
42 int64_t imm = reinterpret_cast<int64_t>(constant->instance().raw());
43 __ movq(RAX, Immediate(imm));
44 } else {
45 __ LoadObject(RAX, value->AsConstant()->instance());
46 }
47 } else {
48 ASSERT(value->IsTemp());
49 Bailout("return of non-ConstantValue value");
50 }
51 }
52
53
54 void FlowGraphCompiler::VisitJoinEntry(JoinEntryInstr* instr) {
55 Bailout("JoinEntryInstr");
56 }
57
58
59 void FlowGraphCompiler::VisitTargetEntry(TargetEntryInstr* instr) {
60 // Since we don't handle branching control flow yet, there is nothing to do.
61 }
62
63
64 void FlowGraphCompiler::VisitDo(DoInstr* instr) {
65 Bailout("DoInstr");
66 }
67
68
69 void FlowGraphCompiler::VisitBind(BindInstr* instr) {
70 Bailout("DoInstr");
71 }
72
73
74 void FlowGraphCompiler::VisitReturn(ReturnInstr* instr) {
75 CompileValue(instr->value());
76
77 #ifdef DEBUG
78 // Check that the entry stack size matches the exit stack size.
79 const intptr_t locals_space_size = 0;
80 __ movq(R10, RBP);
81 __ subq(R10, RSP);
82 __ cmpq(R10, Immediate(locals_space_size));
83 Label stack_ok;
84 __ j(EQUAL, &stack_ok, Assembler::kNearJump);
85 __ Stop("Exit stack size does not match the entry stack size.");
86 __ Bind(&stack_ok);
87 #endif // DEBUG.
88
89 if (FLAG_trace_functions) {
90 __ pushq(RAX); // Preserve result.
91 const Function& function =
92 Function::ZoneHandle(parsed_function_.function().raw());
93 __ LoadObject(RBX, function);
94 __ pushq(RBX);
95 GenerateCallRuntime(AstNode::kNoId,
96 0,
97 kTraceFunctionExitRuntimeEntry);
98 __ popq(RAX); // Remove argument.
99 __ popq(RAX); // Restore result.
100 }
101 __ LeaveFrame();
102 __ ret();
103 }
104
105
106 void FlowGraphCompiler::VisitBranch(BranchInstr* instr) {
107 Bailout("VisitBranch");
108 }
109
110
111 void FlowGraphCompiler::CompileGraph() {
112 const Function& function = parsed_function_.function();
113 if ((function.num_fixed_parameters() != 0) ||
114 (function.num_optional_parameters() != 0)) {
115 Bailout("function has parameters");
116 }
117 LocalScope* scope = parsed_function_.node_sequence()->scope();
118 if (scope->child() != NULL) {
119 Bailout("function has local scopes");
120 }
121 LocalScope* context_owner = NULL;
122 const int first_parameter_index = 1;
123 const int parameter_count = 0;
124 const int first_local_index = -1;
125 int first_free_frame_index =
126 scope->AllocateVariables(first_parameter_index,
127 parameter_count,
128 first_local_index,
129 scope,
130 &context_owner);
131 const int local_count = first_local_index - first_free_frame_index;
132 if (local_count != 0) Bailout("function has locals");
133
134 if (blocks_->length() != 1) Bailout("more than 1 basic block");
135
136 // Specialized version of entry code from CodeGenerator::GenerateEntryCode.
137 __ EnterFrame(0);
138 #ifdef DEBUG
139 const bool check_arguments = true;
140 #else
141 const bool check_arguments = function.IsClosureFunction();
142 #endif
143 if (check_arguments) {
144 // Check that num_fixed <= argc <= num_params.
145 Label argc_in_range;
146 // Total number of args is the first Smi in args descriptor array (R10).
147 __ movq(RAX, FieldAddress(R10, Array::data_offset()));
148 __ cmpq(RAX, Immediate(Smi::RawValue(0)));
149 __ j(EQUAL, &argc_in_range, Assembler::kNearJump);
150 if (function.IsClosureFunction()) {
151 GenerateCallRuntime(AstNode::kNoId,
152 function.token_index(),
153 kClosureArgumentMismatchRuntimeEntry);
154 } else {
155 __ Stop("Wrong number of arguments");
156 }
157 __ Bind(&argc_in_range);
158 }
159 // Generate stack overflow check.
160 __ movq(TMP, Immediate(Isolate::Current()->stack_limit_address()));
161 __ cmpq(RSP, Address(TMP, 0));
162 Label no_stack_overflow;
163 __ j(ABOVE, &no_stack_overflow);
164 GenerateCallRuntime(AstNode::kNoId,
165 function.token_index(),
166 kStackOverflowRuntimeEntry);
167 __ Bind(&no_stack_overflow);
168
169 if (FLAG_print_scopes) {
170 // Print the function scope (again) after generating the prologue in order
171 // to see annotations such as allocation indices of locals.
172 if (FLAG_print_ast) {
173 // Second printing.
174 OS::Print("Annotated ");
175 }
176 AstPrinter::PrintFunctionScope(parsed_function_);
177 }
178
179 VisitBlocks(*blocks_);
180
181 __ int3();
182 // Emit function patching code. This will be swapped with the first 13 bytes
183 // at entry point.
184 pc_descriptors_list_->AddDescriptor(PcDescriptors::kPatchCode,
185 assembler_->CodeSize(),
186 AstNode::kNoId,
187 0,
188 -1);
189 __ jmp(&StubCode::FixCallersTargetLabel());
190
191 if (FLAG_disassemble) {
192 const char* function_fullname = function.ToFullyQualifiedCString();
193 OS::Print(";;; Function %s\n", function_fullname);
194 const Code& code = Code::Handle(Code::FinalizeCode("GRAPH", assembler_));
195 const Instructions& instructions =
196 Instructions::Handle(code.instructions());
197 uword start = instructions.EntryPoint();
198 Disassembler::Disassemble(start, start + assembler_->CodeSize());
199 OS::Print("\n");
200 }
201 }
202
203
204 // Infrastructure copied from class CodeGenerator.
205 void FlowGraphCompiler::GenerateCallRuntime(intptr_t node_id,
206 intptr_t token_index,
207 const RuntimeEntry& entry) {
208 __ CallRuntimeFromDart(entry);
209 AddCurrentDescriptor(PcDescriptors::kOther, node_id, token_index);
210 }
211
212
213 // Uses current pc position and try-index.
214 void FlowGraphCompiler::AddCurrentDescriptor(PcDescriptors::Kind kind,
215 intptr_t node_id,
216 intptr_t token_index) {
217 pc_descriptors_list_->AddDescriptor(kind,
218 assembler_->CodeSize(),
219 node_id,
220 token_index,
221 CatchClauseNode::kInvalidTryIndex);
222 }
223
224
225 } // namespace dart
226
227 #endif // defined TARGET_ARCH_X64
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698