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

Unified Diff: runtime/vm/flow_graph_compiler_arm64.cc

Issue 246293010: Enables first codegen test on arm64. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 8 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
« no previous file with comments | « runtime/vm/flow_graph_compiler_arm.cc ('k') | runtime/vm/flow_graph_compiler_x64.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/flow_graph_compiler_arm64.cc
===================================================================
--- runtime/vm/flow_graph_compiler_arm64.cc (revision 35315)
+++ runtime/vm/flow_graph_compiler_arm64.cc (working copy)
@@ -22,6 +22,9 @@
namespace dart {
+DECLARE_FLAG(int, optimization_counter_threshold);
+DECLARE_FLAG(int, reoptimization_counter_threshold);
+
FlowGraphCompiler::~FlowGraphCompiler() {
// BlockInfos are zone-allocated, so their destructors are not called.
// Verify the labels explicitly here.
@@ -161,7 +164,13 @@
void FlowGraphCompiler::EmitInstructionEpilogue(Instruction* instr) {
- UNIMPLEMENTED();
+ if (is_optimizing()) {
+ return;
+ }
+ Definition* defn = instr->AsDefinition();
+ if ((defn != NULL) && defn->is_used()) {
+ __ Push(defn->locs()->out(0).reg());
+ }
}
@@ -181,12 +190,165 @@
void FlowGraphCompiler::EmitFrameEntry() {
- UNIMPLEMENTED();
+ const Function& function = parsed_function().function();
+ Register new_pp = kNoRegister;
+ if (CanOptimizeFunction() &&
+ function.IsOptimizable() &&
+ (!is_optimizing() || may_reoptimize())) {
+ const Register function_reg = R6;
+ new_pp = R13;
+
+ // Set up pool pointer in new_pp.
+ __ LoadPoolPointer(new_pp);
+
+ // Load function object using the callee's pool pointer.
+ __ LoadObject(function_reg, function, new_pp);
+
+ // Patch point is after the eventually inlined function object.
+ AddCurrentDescriptor(PcDescriptors::kEntryPatch,
+ Isolate::kNoDeoptId,
+ 0); // No token position.
+ intptr_t threshold = FLAG_optimization_counter_threshold;
+ __ LoadFieldFromOffset(R7, function_reg, Function::usage_counter_offset());
+ if (is_optimizing()) {
+ // Reoptimization of an optimized function is triggered by counting in
+ // IC stubs, but not at the entry of the function.
+ threshold = FLAG_reoptimization_counter_threshold;
+ } else {
+ __ add(R7, R7, Operand(1));
+ __ StoreFieldToOffset(R7, function_reg, Function::usage_counter_offset());
+ }
+ __ CompareImmediate(R7, threshold, new_pp);
+ ASSERT(function_reg == R6);
+ Label dont_optimize;
+ __ b(&dont_optimize, LT);
+ __ Branch(&StubCode::OptimizeFunctionLabel(), new_pp);
+ __ Bind(&dont_optimize);
+ } else if (!flow_graph().IsCompiledForOsr()) {
+ // We have to load the PP here too because a load of an external label
+ // may be patched at the AddCurrentDescriptor below.
+ new_pp = R13;
+
+ __ LoadPoolPointer(new_pp);
+
+ AddCurrentDescriptor(PcDescriptors::kEntryPatch,
+ Isolate::kNoDeoptId,
+ 0); // No token position.
+ }
+ __ Comment("Enter frame");
+ if (flow_graph().IsCompiledForOsr()) {
+ intptr_t extra_slots = StackSize()
+ - flow_graph().num_stack_locals()
+ - flow_graph().num_copied_params();
+ ASSERT(extra_slots >= 0);
+ __ EnterOsrFrame(extra_slots * kWordSize, new_pp);
+ } else {
+ ASSERT(StackSize() >= 0);
+ __ EnterDartFrameWithInfo(StackSize() * kWordSize, new_pp);
+ }
}
+// Input parameters:
+// LR: return address.
+// SP: address of last argument.
+// FP: caller's frame pointer.
+// PP: caller's pool pointer.
+// R5: ic-data.
+// R4: arguments descriptor array.
void FlowGraphCompiler::CompileGraph() {
- UNIMPLEMENTED();
+ InitCompiler();
+
+ TryIntrinsify();
+
+ 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();
+
+ // 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.
+ if (num_copied_params == 0) {
+#ifdef DEBUG
+ ASSERT(!parsed_function().function().HasOptionalParameters());
+ const bool check_arguments = !flow_graph().IsCompiledForOsr();
+#else
+ const bool check_arguments =
+ function.IsClosureFunction() && !flow_graph().IsCompiledForOsr();
+#endif
+ if (check_arguments) {
+ __ Comment("Check argument count");
+ // Check that exactly num_fixed arguments are passed in.
+ Label correct_num_arguments, wrong_num_arguments;
+ __ LoadFieldFromOffset(R0, R4, ArgumentsDescriptor::count_offset());
+ __ CompareImmediate(R0, Smi::RawValue(num_fixed_params), PP);
+ __ b(&wrong_num_arguments, NE);
+ __ LoadFieldFromOffset(R1, R4,
+ ArgumentsDescriptor::positional_count_offset());
+ __ CompareRegisters(R0, R1);
+ __ b(&correct_num_arguments, EQ);
+ __ Bind(&wrong_num_arguments);
+ if (function.IsClosureFunction()) {
+ // Invoke noSuchMethod function passing the original function name.
+ // For closure functions, use "call" as the original name.
+ const String& name =
+ String::Handle(function.IsClosureFunction()
+ ? Symbols::Call().raw()
+ : function.name());
+ const int kNumArgsChecked = 1;
+ const ICData& ic_data = ICData::ZoneHandle(
+ ICData::New(function, name, Object::empty_array(),
+ Isolate::kNoDeoptId, kNumArgsChecked));
+ __ LoadObject(R5, ic_data, PP);
+ __ LeaveDartFrame(); // The arguments are still on the stack.
+ __ Branch(&StubCode::CallNoSuchMethodFunctionLabel(), PP);
+ // The noSuchMethod call may return to the caller, but not here.
+ __ hlt(0);
+ } else {
+ __ Stop("Wrong number of arguments");
+ }
+ __ Bind(&correct_num_arguments);
+ }
+ } else if (!flow_graph().IsCompiledForOsr()) {
+ CopyParameters();
+ }
+
+ // In unoptimized code, initialize (non-argument) stack allocated slots to
+ // null.
+ if (!is_optimizing() && (num_locals > 0)) {
+ __ Comment("Initialize spill slots");
+ const intptr_t slot_base = parsed_function().first_stack_local_index();
+ __ LoadObject(R0, Object::null_object(), PP);
+ for (intptr_t i = 0; i < num_locals; ++i) {
+ // Subtract index i (locals lie at lower addresses than FP).
+ __ StoreToOffset(R0, FP, (slot_base - i) * kWordSize);
+ }
+ }
+
+ VisitBlocks();
+
+ __ hlt(0);
+ GenerateDeferredCode();
+ // Emit function patching code. This will be swapped with the first 3
+ // instructions at entry point.
+ AddCurrentDescriptor(PcDescriptors::kPatchCode,
+ Isolate::kNoDeoptId,
+ 0); // No token position.
+ // This is patched up to a point in FrameEntry where the PP for the
+ // current function is in R13 instead of PP.
+ __ BranchPatchable(&StubCode::FixCallersTargetLabel(), R13);
+
+ AddCurrentDescriptor(PcDescriptors::kLazyDeoptJump,
+ Isolate::kNoDeoptId,
+ 0); // No token position.
+ // TODO(zra): Can I use a normal BranchPatchable here? Probably have to change
+ // the CodePatcher.
+ __ BranchFixed(&StubCode::DeoptimizeLazyLabel());
}
@@ -212,12 +374,37 @@
const RuntimeEntry& entry,
intptr_t argument_count,
LocationSummary* locs) {
- UNIMPLEMENTED();
+ __ CallRuntime(entry, argument_count);
+ AddCurrentDescriptor(PcDescriptors::kOther, deopt_id, token_pos);
+ RecordSafepoint(locs);
+ if (deopt_id != Isolate::kNoDeoptId) {
+ // Marks either the continuation point in unoptimized code or the
+ // deoptimization point in optimized code, after call.
+ const intptr_t deopt_id_after = Isolate::ToDeoptAfter(deopt_id);
+ if (is_optimizing()) {
+ AddDeoptIndexAtCall(deopt_id_after, token_pos);
+ } else {
+ // Add deoptimization continuation point after the call and before the
+ // arguments are removed.
+ AddCurrentDescriptor(PcDescriptors::kDeopt, deopt_id_after, token_pos);
+ }
+ }
}
void FlowGraphCompiler::EmitEdgeCounter() {
- UNIMPLEMENTED();
+ // We do not check for overflow when incrementing the edge counter. The
+ // function should normally be optimized long before the counter can
+ // overflow; and though we do not reset the counters when we optimize or
+ // deoptimize, there is a bound on the number of
+ // optimization/deoptimization cycles we will attempt.
+ const Array& counter = Array::ZoneHandle(Array::New(1, Heap::kOld));
+ counter.SetAt(0, Smi::Handle(Smi::New(0)));
+ __ Comment("Edge counter");
+ __ LoadObject(R0, counter, PP);
+ __ LoadFieldFromOffset(TMP, R0, Array::element_offset(0));
+ __ add(TMP, TMP, Operand(Smi::RawValue(1)));
+ __ StoreFieldToOffset(TMP, R0, Array::element_offset(0));
}
@@ -293,12 +480,30 @@
// This function must be in sync with FlowGraphCompiler::RecordSafepoint and
// FlowGraphCompiler::SlowPathEnvironmentFor.
void FlowGraphCompiler::SaveLiveRegisters(LocationSummary* locs) {
- UNIMPLEMENTED();
+ // TODO(zra): Save live FPU Registers.
+
+ // Store general purpose registers with the highest register number at the
+ // lowest address.
+ for (intptr_t reg_idx = 0; reg_idx < kNumberOfCpuRegisters; ++reg_idx) {
+ Register reg = static_cast<Register>(reg_idx);
+ if (locs->live_registers()->ContainsRegister(reg)) {
+ __ Push(reg);
+ }
+ }
}
void FlowGraphCompiler::RestoreLiveRegisters(LocationSummary* locs) {
- UNIMPLEMENTED();
+ // General purpose registers have the highest register number at the
+ // lowest address.
+ for (intptr_t reg_idx = kNumberOfCpuRegisters - 1; reg_idx >= 0; --reg_idx) {
+ Register reg = static_cast<Register>(reg_idx);
+ if (locs->live_registers()->ContainsRegister(reg)) {
+ __ Pop(reg);
+ }
+ }
+
+ // TODO(zra): Restore live FPU registers.
}
« no previous file with comments | « runtime/vm/flow_graph_compiler_arm.cc ('k') | runtime/vm/flow_graph_compiler_x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698