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

Unified Diff: runtime/vm/flow_graph_compiler_arm.cc

Issue 12335102: Compile and simulate first dart function on arm generated from ast. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 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_arm.cc
===================================================================
--- runtime/vm/flow_graph_compiler_arm.cc (revision 19074)
+++ runtime/vm/flow_graph_compiler_arm.cc (working copy)
@@ -7,10 +7,24 @@
#include "vm/flow_graph_compiler.h"
-#include "vm/longjump.h"
+#include "lib/error.h"
+#include "vm/ast_printer.h"
+#include "vm/dart_entry.h"
+#include "vm/il_printer.h"
+#include "vm/locations.h"
+#include "vm/object_store.h"
+#include "vm/parser.h"
+#include "vm/stub_code.h"
+#include "vm/symbols.h"
namespace dart {
+DECLARE_FLAG(int, optimization_counter_threshold);
+DECLARE_FLAG(bool, print_ast);
+DECLARE_FLAG(bool, print_scopes);
+DECLARE_FLAG(bool, enable_type_checks);
+
+
FlowGraphCompiler::~FlowGraphCompiler() {
// BlockInfos are zone-allocated, so their destructors are not called.
// Verify the labels explicitly here.
@@ -31,6 +45,9 @@
}
+#define __ assembler()->
+
+
void FlowGraphCompiler::GenerateBoolToJump(Register bool_register,
Label* is_true,
Label* is_false) {
@@ -128,12 +145,24 @@
void FlowGraphCompiler::EmitInstructionPrologue(Instruction* instr) {
- UNIMPLEMENTED();
+ if (!is_optimizing()) {
+ if (FLAG_enable_type_checks && instr->IsAssertAssignable()) {
+ AssertAssignableInstr* assert = instr->AsAssertAssignable();
+ AddCurrentDescriptor(PcDescriptors::kDeoptBefore,
+ assert->deopt_id(),
+ assert->token_pos());
+ }
+ AllocateRegistersLocally(instr);
+ }
}
void FlowGraphCompiler::EmitInstructionEpilogue(Instruction* instr) {
- UNIMPLEMENTED();
+ if (is_optimizing()) return;
+ Definition* defn = instr->AsDefinition();
+ if ((defn != NULL) && defn->is_used()) {
+ __ Push(defn->locs()->out().reg());
+ }
}
@@ -153,12 +182,191 @@
void FlowGraphCompiler::EmitFrameEntry() {
- UNIMPLEMENTED();
+ const Function& function = parsed_function().function();
+ if (CanOptimizeFunction() && function.is_optimizable()) {
+ const bool can_optimize = !is_optimizing() || may_reoptimize();
+ const Register function_reg = R6;
+ if (can_optimize) {
+ __ LoadObject(function_reg, function);
+ }
+ // Patch point is after the eventually inlined function object.
+ AddCurrentDescriptor(PcDescriptors::kEntryPatch,
+ Isolate::kNoDeoptId,
+ 0); // No token position.
+ if (can_optimize) {
+ // Reoptimization of optimized function is triggered by counting in
+ // IC stubs, but not at the entry of the function.
+ if (!is_optimizing()) {
+ __ ldr(R7, FieldAddress(function_reg,
+ Function::usage_counter_offset()));
+ __ add(R7, R7, ShifterOperand(1));
+ __ str(R7, FieldAddress(function_reg,
+ Function::usage_counter_offset()));
+ } else {
+ __ ldr(R7, FieldAddress(function_reg,
+ Function::usage_counter_offset()));
+ }
+ __ CompareImmediate(R7, FLAG_optimization_counter_threshold);
+ ASSERT(function_reg == R6);
+ __ Branch(&StubCode::OptimizeFunctionLabel(), GE);
+ }
+ } else {
+ AddCurrentDescriptor(PcDescriptors::kEntryPatch,
+ Isolate::kNoDeoptId,
+ 0); // No token position.
+ }
+ __ Comment("Enter frame");
+ AssemblerMacros::EnterDartFrame(assembler(), (StackSize() * kWordSize));
}
void FlowGraphCompiler::CompileGraph() {
- UNIMPLEMENTED();
+ InitCompiler();
+ if (TryIntrinsify()) {
+ // Although this intrinsified code will never be patched, it must satisfy
+ // CodePatcher::CodeIsPatchable, which verifies that this code has a minimum
+ // code size.
+ __ bkpt(0);
+ __ Branch(&StubCode::FixCallersTargetLabel());
+ return;
+ }
+
+ EmitFrameEntry();
+
+ const Function& function = parsed_function().function();
+
+ const int num_fixed_params = function.num_fixed_parameters();
+ const int num_copied_params = parsed_function().num_copied_params();
+ const int num_locals = parsed_function().num_stack_locals();
+
+ // For optimized code, keep a bitmap of the frame in order to build
+ // stackmaps for GC safepoints in the prologue.
+ LocationSummary* prologue_locs = NULL;
+ if (is_optimizing()) {
+ // Spill slots are allocated but not initialized.
+ prologue_locs = new LocationSummary(0, 0, LocationSummary::kCall);
+ prologue_locs->stack_bitmap()->SetLength(StackSize());
+ }
+
+ // We check the number of passed arguments when we have to copy them due to
+ // the presence of optional parameters.
+ // No such checking code is generated if only fixed parameters are declared,
+ // unless we are in debug mode or unless we are compiling a closure.
+ LocalVariable* saved_args_desc_var =
+ parsed_function().GetSavedArgumentsDescriptorVar();
+ if (num_copied_params == 0) {
+#ifdef DEBUG
+ ASSERT(!parsed_function().function().HasOptionalParameters());
+ const bool check_arguments = true;
+#else
+ const bool check_arguments = function.IsClosureFunction();
+#endif
+ if (check_arguments) {
+ __ Comment("Check argument count");
+ // Check that exactly num_fixed arguments are passed in.
+ Label correct_num_arguments, wrong_num_arguments;
+ __ ldr(R0, FieldAddress(R4, ArgumentsDescriptor::count_offset()));
+ __ CompareImmediate(R0, Smi::RawValue(num_fixed_params));
+ __ b(&wrong_num_arguments, NE);
+ __ ldr(R1, FieldAddress(R4,
+ ArgumentsDescriptor::positional_count_offset()));
+ __ cmp(R0, ShifterOperand(R1));
+ __ b(&correct_num_arguments, EQ);
+ __ Bind(&wrong_num_arguments);
+ if (function.IsClosureFunction()) {
+ if (StackSize() != 0) {
+ // We need to unwind the space we reserved for locals and copied
+ // parameters. The NoSuchMethodFunction stub does not expect to see
+ // that area on the stack.
+ __ AddImmediate(SP, StackSize() * kWordSize);
+ }
+ // The call below has an empty stackmap because we have just
+ // dropped the spill slots.
+ BitmapBuilder* empty_stack_bitmap = new BitmapBuilder();
+
+ // Invoke noSuchMethod function passing "call" as the function name.
+ const int kNumArgsChecked = 1;
+ const ICData& ic_data = ICData::ZoneHandle(
+ ICData::New(function, Symbols::Call(),
+ Isolate::kNoDeoptId, kNumArgsChecked));
+ __ LoadObject(R5, ic_data);
+ // FP - 4 : saved PP, object pool pointer of caller.
+ // FP + 0 : previous frame pointer.
+ // FP + 4 : return address.
+ // FP + 8 : PC marker, for easy identification of RawInstruction obj.
+ // FP + 12: last argument (arg n-1).
+ // SP + 0 : saved PP.
+ // SP + 16 + 4*(n-1) : first argument (arg 0).
+ // R5 : ic-data.
+ // R4 : arguments descriptor array.
+ __ BranchLink(&StubCode::CallNoSuchMethodFunctionLabel());
+ if (is_optimizing()) {
+ stackmap_table_builder_->AddEntry(assembler()->CodeSize(),
+ empty_stack_bitmap,
+ 0); // No registers.
+ }
+ // The noSuchMethod call may return.
+ AssemblerMacros::LeaveDartFrame(assembler());
+ __ Ret();
+ } else {
+ __ Stop("Wrong number of arguments");
+ }
+ __ Bind(&correct_num_arguments);
+ }
+ // The arguments descriptor is never saved in the absence of optional
+ // parameters, since any argument definition test would always yield true.
+ ASSERT(saved_args_desc_var == NULL);
+ } else {
+ if (saved_args_desc_var != NULL) {
+ __ Comment("Save arguments descriptor");
+ const Register kArgumentsDescriptorReg = R4;
+ // The saved_args_desc_var is allocated one slot before the first local.
+ const intptr_t slot = parsed_function().first_stack_local_index() + 1;
+ // If the saved_args_desc_var is captured, it is first moved to the stack
+ // and later to the context, once the context is allocated.
+ ASSERT(saved_args_desc_var->is_captured() ||
+ (saved_args_desc_var->index() == slot));
+ __ str(kArgumentsDescriptorReg, Address(FP, slot * kWordSize));
+ }
+ CopyParameters();
+ }
+
+ // In unoptimized code, initialize (non-argument) stack allocated slots to
+ // null. This does not cover the saved_args_desc_var slot.
+ if (!is_optimizing() && (num_locals > 0)) {
+ __ Comment("Initialize spill slots");
+ const intptr_t slot_base = parsed_function().first_stack_local_index();
+ __ LoadImmediate(R0, reinterpret_cast<intptr_t>(Object::null()));
+ for (intptr_t i = 0; i < num_locals; ++i) {
+ // Subtract index i (locals lie at lower addresses than FP).
+ __ str(R0, Address(FP, (slot_base - i) * kWordSize));
+ }
+ }
+
+ 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();
+
+ __ bkpt(0);
+ GenerateDeferredCode();
+ // Emit function patching code. This will be swapped with the first 5 bytes
+ // at entry point.
+ AddCurrentDescriptor(PcDescriptors::kPatchCode,
+ Isolate::kNoDeoptId,
+ 0); // No token position.
+ __ Branch(&StubCode::FixCallersTargetLabel());
+ AddCurrentDescriptor(PcDescriptors::kLazyDeoptJump,
+ Isolate::kNoDeoptId,
+ 0); // No token position.
+ __ Branch(&StubCode::DeoptimizeLazyLabel());
}
@@ -183,7 +391,7 @@
intptr_t deopt_id,
const RuntimeEntry& entry,
LocationSummary* locs) {
- UNIMPLEMENTED();
+ __ Unimplemented("call runtime");
}
@@ -252,12 +460,31 @@
void FlowGraphCompiler::SaveLiveRegisters(LocationSummary* locs) {
- UNIMPLEMENTED();
+ // TODO(vegorov): consider saving only caller save (volatile) registers.
+ const intptr_t fpu_registers = locs->live_registers()->fpu_registers();
+ if (fpu_registers > 0) {
+ UNIMPLEMENTED();
+ }
+
+ // Store general purpose registers with the lowest register number at the
+ // lowest address.
+ const intptr_t cpu_registers = locs->live_registers()->cpu_registers();
+ ASSERT((cpu_registers & ~kAllCpuRegistersList) == 0);
+ __ PushList(cpu_registers);
}
void FlowGraphCompiler::RestoreLiveRegisters(LocationSummary* locs) {
- UNIMPLEMENTED();
+ // General purpose registers have the lowest register number at the
+ // lowest address.
+ const intptr_t cpu_registers = locs->live_registers()->cpu_registers();
+ ASSERT((cpu_registers & ~kAllCpuRegistersList) == 0);
+ __ PopList(cpu_registers);
+
+ const intptr_t fpu_registers = locs->live_registers()->fpu_registers();
+ if (fpu_registers > 0) {
+ UNIMPLEMENTED();
+ }
}

Powered by Google App Engine
This is Rietveld 408576698