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

Unified Diff: runtime/vm/flow_graph_compiler_mips.cc

Issue 13228002: First two codegen tests passing on SIMMIPS (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 9 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/disassembler_mips.cc ('k') | runtime/vm/instructions_mips.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/flow_graph_compiler_mips.cc
===================================================================
--- runtime/vm/flow_graph_compiler_mips.cc (revision 20729)
+++ runtime/vm/flow_graph_compiler_mips.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,221 @@
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 = T0;
+ if (can_optimize) {
+ Label next;
+ // The pool pointer is not setup before entering the Dart frame.
+
+ __ mov(TMP, RA); // Save RA.
+ __ bal(&next); // Branch and link to next instruction to get PC in RA.
+ __ delay_slot()->mov(T2, RA); // Save PC of the following mov.
+
+ // Calculate offset of pool pointer from the PC.
+ const intptr_t object_pool_pc_dist =
+ Instructions::HeaderSize() - Instructions::object_pool_offset() +
+ assembler()->CodeSize();
+
+ __ Bind(&next);
+ __ mov(RA, TMP); // Restore RA.
+
+ // Preserve PP of caller.
+ __ mov(T1, PP);
+
+ // Temporarily setup pool pointer for this dart function.
+ __ lw(PP, Address(T2, -object_pool_pc_dist));
+
+ // Load function object from object pool.
+ __ LoadObject(function_reg, function); // Uses PP.
+
+ // Restore PP of caller.
+ __ mov(PP, T1);
+ }
+ // 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()) {
+ __ lw(T1, FieldAddress(function_reg,
+ Function::usage_counter_offset()));
+ __ addiu(T1, T1, Immediate(1));
+ __ sw(T1, FieldAddress(function_reg,
+ Function::usage_counter_offset()));
+ } else {
+ __ lw(T1, FieldAddress(function_reg,
+ Function::usage_counter_offset()));
+ }
+
+ // Skip Branch if T1 is less than the threshold.
+ Label dont_branch;
+ __ LoadImmediate(T2, FLAG_optimization_counter_threshold);
+ __ sltu(T2, T1, T2);
+ __ bgtz(T2, &dont_branch);
+
+ ASSERT(function_reg == T0);
+ __ Branch(&StubCode::OptimizeFunctionLabel());
+
+ __ Bind(&dont_branch);
+ }
+ } else {
+ AddCurrentDescriptor(PcDescriptors::kEntryPatch,
+ Isolate::kNoDeoptId,
+ 0); // No token position.
+ }
+ __ Comment("Enter frame");
+ __ EnterDartFrame((StackSize() * kWordSize));
}
+// Input parameters:
+// RA: return address.
+// SP: address of last argument.
+// FP: caller's frame pointer.
+// PP: caller's pool pointer.
+// S5: ic-data.
+// S4: arguments descriptor array.
+void FlowGraphCompiler::CompileGraph() {
+ 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.
+ __ break_(0);
+ __ Branch(&StubCode::FixCallersTargetLabel());
+ return;
+ }
-void FlowGraphCompiler::CompileGraph() {
- UNIMPLEMENTED();
+ 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.
+ 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;
+ __ lw(T0, FieldAddress(S4, ArgumentsDescriptor::count_offset()));
+ __ LoadImmediate(T1, Smi::RawValue(num_fixed_params));
+ __ bne(T0, T1, &wrong_num_arguments);
+
+ __ lw(T1, FieldAddress(S4,
+ ArgumentsDescriptor::positional_count_offset()));
+ __ beq(T0, T1, &correct_num_arguments);
+ __ 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.
+ __ addiu(SP, SP, Immediate(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(S5, 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).
+ // S5 : ic-data.
+ // S4 : 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.
+ __ LeaveDartFrame();
+ __ 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 = S4;
+ // 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));
+ __ sw(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(T0, 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).
+ __ sw(T0, 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();
+
+ __ break_(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 +421,7 @@
intptr_t deopt_id,
const RuntimeEntry& entry,
LocationSummary* locs) {
- UNIMPLEMENTED();
+ __ Unimplemented("call runtime");
}
@@ -252,12 +490,51 @@
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);
+ const int register_count = Utils::CountOneBits(cpu_registers);
+ int registers_pushed = 0;
+
+ __ addiu(SP, SP, Immediate(-register_count * kWordSize));
+ for (int i = 0; i < kNumberOfCpuRegisters; i++) {
+ Register r = static_cast<Register>(i);
+ if (locs->live_registers()->ContainsRegister(r)) {
+ __ sw(r, Address(SP, registers_pushed * kWordSize));
+ registers_pushed++;
+ }
+ }
}
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);
+ const int register_count = Utils::CountOneBits(cpu_registers);
+ int registers_popped = 0;
+
+ for (int i = 0; i < kNumberOfCpuRegisters; i++) {
+ Register r = static_cast<Register>(i);
+ if (locs->live_registers()->ContainsRegister(r)) {
+ __ lw(r, Address(SP, registers_popped * kWordSize));
+ registers_popped++;
+ }
+ }
+ __ addiu(SP, SP, Immediate(register_count * kWordSize));
+
+ const intptr_t fpu_registers = locs->live_registers()->fpu_registers();
+ if (fpu_registers > 0) {
+ UNIMPLEMENTED();
+ }
}
« no previous file with comments | « runtime/vm/disassembler_mips.cc ('k') | runtime/vm/instructions_mips.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698