Move resolving of natives to a late stage (during code emission). That eliminates unnecessary native resolution (e.g., when native gets recognized or rejected in the inliner). Removed tests that are now impossible to implement with AST (fake native functions).

BUG=
R=hausner@google.com

Review URL: https://codereview.chromium.org/1420173006 .
This commit is contained in:
Srdjan Mitrovic
2015-11-03 16:18:24 -08:00
parent aaaf7c2de8
commit 181e8cc2a9
12 changed files with 58 additions and 244 deletions
-9
View File
@@ -1814,19 +1814,14 @@ class NativeBodyNode : public AstNode {
NativeBodyNode(intptr_t token_pos,
const Function& function,
const String& native_c_function_name,
NativeFunction native_c_function,
LocalScope* scope,
bool is_bootstrap_native,
bool link_lazily = false)
: AstNode(token_pos),
function_(function),
native_c_function_name_(native_c_function_name),
native_c_function_(native_c_function),
scope_(scope),
is_bootstrap_native_(is_bootstrap_native),
link_lazily_(link_lazily) {
ASSERT(function_.IsZoneHandle());
ASSERT(native_c_function_ != NULL);
ASSERT(native_c_function_name_.IsZoneHandle());
ASSERT(native_c_function_name_.IsSymbol());
}
@@ -1835,9 +1830,7 @@ class NativeBodyNode : public AstNode {
const String& native_c_function_name() const {
return native_c_function_name_;
}
NativeFunction native_c_function() const { return native_c_function_; }
LocalScope* scope() const { return scope_; }
bool is_bootstrap_native() const { return is_bootstrap_native_; }
bool link_lazily() const { return link_lazily_; }
@@ -1848,9 +1841,7 @@ class NativeBodyNode : public AstNode {
private:
const Function& function_; // Native Dart function.
const String& native_c_function_name_;
NativeFunction native_c_function_; // Actual non-Dart implementation.
LocalScope* scope_;
const bool is_bootstrap_native_; // Is a bootstrap native method.
const bool link_lazily_;
DISALLOW_IMPLICIT_CONSTRUCTORS(NativeBodyNode);
-205
View File
@@ -192,58 +192,6 @@ CODEGEN_TEST_GENERATE(BinaryOpCodegen, test) {
CODEGEN_TEST_RUN(BinaryOpCodegen, Double::New(2.5));
// Tested Dart code:
// int dec(int a, [int b = 1]) native: "TestSmiSub";
// The native entry TestSmiSub implements dec natively.
CODEGEN_TEST_GENERATE(NativeDecCodegen, test) {
// A NativeBodyNode, preceded by an EnterNode and followed by a ReturnNode,
// implements the body of a native Dart function. Let's take this native
// function as an example: int dec(int a, int b = 1) native;
// Since this function has an optional parameter, its prologue will copy
// incoming parameters to locals.
SequenceNode* node_seq = test->node_sequence();
const int num_fixed_params = 1;
const int num_opt_params = 1;
const int num_params = num_fixed_params + num_opt_params;
LocalScope* local_scope = node_seq->scope();
local_scope->InsertParameterAt(0, NewTestLocalVariable("a"));
local_scope->InsertParameterAt(1, NewTestLocalVariable("b"));
ASSERT(local_scope->num_variables() == num_params);
ZoneGrowableArray<const Instance*>* default_values =
new ZoneGrowableArray<const Instance*>(num_opt_params);
default_values->Add(&Smi::ZoneHandle(Smi::New(1))); // b = 1.
test->set_default_parameter_values(default_values);
const Function& function = test->function();
function.set_is_native(true);
function.set_num_fixed_parameters(num_fixed_params);
function.SetNumOptionalParameters(num_opt_params, true);
const String& native_name =
String::ZoneHandle(Symbols::New("TestSmiSub"));
NativeFunction native_function =
reinterpret_cast<NativeFunction>(TestSmiSub);
node_seq->Add(
new ReturnNode(kPos,
new NativeBodyNode(kPos,
function,
native_name,
native_function,
local_scope,
false /* not bootstrap native */)));
}
// Tested Dart code:
// return dec(5);
CODEGEN_TEST2_GENERATE(StaticDecCallCodegen, function, test) {
SequenceNode* node_seq = test->node_sequence();
ArgumentListNode* arguments = new ArgumentListNode(kPos);
arguments->Add(new LiteralNode(kPos, Smi::ZoneHandle(Smi::New(5))));
node_seq->Add(new ReturnNode(kPos,
new StaticCallNode(kPos, function, arguments)));
}
CODEGEN_TEST2_RUN(StaticDecCallCodegen, NativeDecCodegen, Smi::New(4))
CODEGEN_TEST_GENERATE(SmiUnaryOpCodegen, test) {
SequenceNode* node_seq = test->node_sequence();
LiteralNode* a = new LiteralNode(kPos, Smi::ZoneHandle(Smi::New(12)));
@@ -368,159 +316,6 @@ CODEGEN_TEST_GENERATE(InstanceCallCodegen, test) {
CODEGEN_TEST_RUN(InstanceCallCodegen, Smi::New(42))
// Tested Dart code:
// int sum(int a, int b,
// [int c = 10, int d = 21, int e = -32]) native: "TestSmiSum";
// The native entry TestSmiSum implements sum natively.
CODEGEN_TEST_GENERATE(NativeSumCodegen, test) {
SequenceNode* node_seq = test->node_sequence();
const int num_fixed_params = 2;
const int num_opt_params = 3;
const int num_params = num_fixed_params + num_opt_params;
LocalScope* local_scope = node_seq->scope();
local_scope->InsertParameterAt(0, NewTestLocalVariable("a"));
local_scope->InsertParameterAt(1, NewTestLocalVariable("b"));
local_scope->InsertParameterAt(2, NewTestLocalVariable("c"));
local_scope->InsertParameterAt(3, NewTestLocalVariable("d"));
local_scope->InsertParameterAt(4, NewTestLocalVariable("e"));
ASSERT(local_scope->num_variables() == num_params);
ZoneGrowableArray<const Instance*>* default_values =
new ZoneGrowableArray<const Instance*>(num_opt_params);
default_values->Add(&Smi::ZoneHandle(Smi::New(10)));
default_values->Add(&Smi::ZoneHandle(Smi::New(21)));
default_values->Add(&Smi::ZoneHandle(Smi::New(-32)));
test->set_default_parameter_values(default_values);
const Function& function = test->function();
function.set_is_native(true);
function.set_num_fixed_parameters(num_fixed_params);
function.SetNumOptionalParameters(num_opt_params, true);
function.set_parameter_types(Array::Handle(Array::New(num_params)));
function.set_parameter_names(Array::Handle(Array::New(num_params)));
const Type& param_type = Type::Handle(Type::DynamicType());
for (int i = 0; i < num_params; i++) {
function.SetParameterTypeAt(i, param_type);
}
const String& native_name =
String::ZoneHandle(Symbols::New("TestSmiSum"));
NativeFunction native_function =
reinterpret_cast<NativeFunction>(TestSmiSum);
node_seq->Add(
new ReturnNode(kPos,
new NativeBodyNode(kPos,
function,
native_name,
native_function,
local_scope,
false /* Not bootstrap native */)));
}
// Tested Dart code, calling function sum declared above:
// return sum(1, 3);
// Optional arguments are not passed and hence are set to their default values.
CODEGEN_TEST2_GENERATE(StaticSumCallNoOptCodegen, function, test) {
SequenceNode* node_seq = test->node_sequence();
ArgumentListNode* arguments = new ArgumentListNode(kPos);
arguments->Add(new LiteralNode(kPos, Smi::ZoneHandle(Smi::New(1))));
arguments->Add(new LiteralNode(kPos, Smi::ZoneHandle(Smi::New(3))));
node_seq->Add(new ReturnNode(kPos,
new StaticCallNode(kPos, function, arguments)));
}
CODEGEN_TEST2_RUN(StaticSumCallNoOptCodegen,
NativeSumCodegen,
Smi::New(1 + 3 + 10 + 21 - 32))
// Tested Dart code, calling function sum declared above:
// return sum(1, 3, 5);
// Only one out of three optional arguments is passed in; the second and third
// arguments are hence set to their default values.
CODEGEN_TEST2_GENERATE(StaticSumCallOneOptCodegen, function, test) {
SequenceNode* node_seq = test->node_sequence();
ArgumentListNode* arguments = new ArgumentListNode(kPos);
arguments->Add(new LiteralNode(kPos, Smi::ZoneHandle(Smi::New(1))));
arguments->Add(new LiteralNode(kPos, Smi::ZoneHandle(Smi::New(3))));
arguments->Add(new LiteralNode(kPos, Smi::ZoneHandle(Smi::New(5))));
node_seq->Add(new ReturnNode(kPos,
new StaticCallNode(kPos, function, arguments)));
}
CODEGEN_TEST2_RUN(StaticSumCallOneOptCodegen,
NativeSumCodegen,
Smi::New(1 + 3 + 5 + 21 - 32))
// Tested Dart code, calling function sum declared above:
// return sum(0, 1, 1, 2, 3);
// Optional arguments are passed in.
CODEGEN_TEST2_GENERATE(StaticSumCallTenFiboCodegen, function, test) {
SequenceNode* node_seq = test->node_sequence();
ArgumentListNode* arguments = new ArgumentListNode(kPos);
arguments->Add(new LiteralNode(kPos, Smi::ZoneHandle(Smi::New(0))));
arguments->Add(new LiteralNode(kPos, Smi::ZoneHandle(Smi::New(1))));
arguments->Add(new LiteralNode(kPos, Smi::ZoneHandle(Smi::New(1))));
arguments->Add(new LiteralNode(kPos, Smi::ZoneHandle(Smi::New(2))));
arguments->Add(new LiteralNode(kPos, Smi::ZoneHandle(Smi::New(3))));
node_seq->Add(new ReturnNode(kPos,
new StaticCallNode(kPos, function, arguments)));
}
CODEGEN_TEST2_RUN(
StaticSumCallTenFiboCodegen,
NativeSumCodegen,
Smi::New(0 + 1 + 1 + 2 + 3))
// Tested Dart code:
// int sum(a, b, c) native: "TestNonNullSmiSum";
// The native entry TestNonNullSmiSum implements sum natively.
CODEGEN_TEST_GENERATE(NativeNonNullSumCodegen, test) {
SequenceNode* node_seq = test->node_sequence();
const int num_params = 3;
LocalScope* local_scope = node_seq->scope();
local_scope->InsertParameterAt(0, NewTestLocalVariable("a"));
local_scope->InsertParameterAt(1, NewTestLocalVariable("b"));
local_scope->InsertParameterAt(2, NewTestLocalVariable("c"));
ASSERT(local_scope->num_variables() == num_params);
const Function& function = test->function();
function.set_is_native(true);
function.set_num_fixed_parameters(num_params);
ASSERT(!function.HasOptionalParameters());
function.set_parameter_types(Array::Handle(Array::New(num_params)));
function.set_parameter_names(Array::Handle(Array::New(num_params)));
const Type& param_type = Type::Handle(Type::DynamicType());
for (int i = 0; i < num_params; i++) {
function.SetParameterTypeAt(i, param_type);
}
const String& native_name =
String::ZoneHandle(Symbols::New("TestNonNullSmiSum"));
NativeFunction native_function =
reinterpret_cast<NativeFunction>(TestNonNullSmiSum);
node_seq->Add(
new ReturnNode(kPos,
new NativeBodyNode(kPos,
function,
native_name,
native_function,
local_scope,
false /* Not bootstrap native */)));
}
// Tested Dart code, calling function sum declared above:
// return sum(1, null, 3);
CODEGEN_TEST2_GENERATE(StaticNonNullSumCallCodegen, function, test) {
SequenceNode* node_seq = test->node_sequence();
ArgumentListNode* arguments = new ArgumentListNode(kPos);
arguments->Add(new LiteralNode(kPos, Smi::ZoneHandle(Smi::New(1))));
arguments->Add(new LiteralNode(kPos, Instance::ZoneHandle()));
arguments->Add(new LiteralNode(kPos, Smi::ZoneHandle(Smi::New(3))));
node_seq->Add(new ReturnNode(kPos,
new StaticCallNode(kPos, function, arguments)));
}
CODEGEN_TEST2_RUN(StaticNonNullSumCallCodegen,
NativeNonNullSumCodegen,
Smi::New(1 + 3))
// Test allocation of dart objects.
CODEGEN_TEST_GENERATE(AllocateNewObjectCodegen, test) {
const char* kScriptChars =
+7 -2
View File
@@ -852,7 +852,6 @@ static bool CompileParsedFunctionHelper(CompilationPipeline* pipeline,
THR_Print("%s\n", error.ToErrorCString());
}
done = true;
ASSERT(optimized);
}
// Clear the error if it was not a real error, but just a bailout.
@@ -1091,8 +1090,14 @@ static RawError* CompileFunctionHelper(CompilationPipeline* pipeline,
}
function.SetIsOptimizable(false);
return Error::null();
} else {
// Encountered error.
Error& error = Error::Handle();
// We got an error during compilation.
error = isolate->object_store()->sticky_error();
isolate->object_store()->clear_sticky_error();
return error.raw();
}
UNREACHABLE();
}
per_compile_timer.Stop();
+25
View File
@@ -5,6 +5,7 @@
#include "vm/intermediate_language.h"
#include "vm/bit_vector.h"
#include "vm/bootstrap.h"
#include "vm/compiler.h"
#include "vm/constant_propagator.h"
#include "vm/cpu.h"
@@ -3656,6 +3657,30 @@ intptr_t MergedMathInstr::OutputIndexOf(Token::Kind token) {
}
void NativeCallInstr::SetupNative() {
Zone* Z = Thread::Current()->zone();
const Class& cls = Class::Handle(Z, function().Owner());
const Library& library = Library::Handle(Z, cls.library());
const int num_params =
NativeArguments::ParameterCountForResolution(function());
bool auto_setup_scope = true;
NativeFunction native_function = NativeEntry::ResolveNative(
library, native_name(), num_params, &auto_setup_scope);
if (native_function == NULL) {
Report::MessageF(Report::kError,
Script::Handle(function().script()),
function().token_pos(),
"native function '%s' (%" Pd " arguments) cannot be found",
native_name().ToCString(),
function().NumParameters());
}
set_native_c_function(native_function);
function().SetIsNativeAutoSetupScope(auto_setup_scope);
Dart_NativeEntryResolver resolver = library.native_entry_resolver();
bool is_bootstrap_native = Bootstrap::IsBootstapResolver(resolver);
set_is_bootstrap_native(is_bootstrap_native);
}
#undef __
} // namespace dart
+15 -3
View File
@@ -3393,7 +3393,9 @@ class StoreLocalInstr : public TemplateDefinition<1, NoThrow> {
class NativeCallInstr : public TemplateDefinition<0, Throws> {
public:
explicit NativeCallInstr(NativeBodyNode* node)
: ast_node_(*node) {}
: ast_node_(*node),
native_c_function_(NULL),
is_bootstrap_native_(false) { }
DECLARE_INSTRUCTION(NativeCall)
@@ -3406,11 +3408,11 @@ class NativeCallInstr : public TemplateDefinition<0, Throws> {
}
NativeFunction native_c_function() const {
return ast_node_.native_c_function();
return native_c_function_;
}
bool is_bootstrap_native() const {
return ast_node_.is_bootstrap_native();
return is_bootstrap_native_;
}
bool link_lazily() const {
@@ -3423,8 +3425,18 @@ class NativeCallInstr : public TemplateDefinition<0, Throws> {
virtual EffectSet Effects() const { return EffectSet::All(); }
void SetupNative();
private:
void set_native_c_function(NativeFunction value) {
native_c_function_ = value;
}
void set_is_bootstrap_native(bool value) { is_bootstrap_native_ = value; }
const NativeBodyNode& ast_node_;
NativeFunction native_c_function_;
bool is_bootstrap_native_;
DISALLOW_COPY_AND_ASSIGN(NativeCallInstr);
};
+2 -1
View File
@@ -925,6 +925,7 @@ LocationSummary* NativeCallInstr::MakeLocationSummary(Zone* zone,
void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
SetupNative();
const Register result = locs()->out(0).reg();
// Push the result place holder initialized to NULL.
@@ -942,7 +943,7 @@ void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
uword entry;
const intptr_t argc_tag = NativeArguments::ComputeArgcTag(function());
const bool is_leaf_call =
(argc_tag & NativeArguments::AutoSetupScopeMask()) == 0;
(argc_tag & NativeArguments::AutoSetupScopeMask()) == 0;
const StubEntry* stub_entry;
if (link_lazily()) {
stub_entry = StubCode::CallBootstrapCFunction_entry();
+2 -1
View File
@@ -779,6 +779,7 @@ LocationSummary* NativeCallInstr::MakeLocationSummary(Zone* zone,
void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
SetupNative();
const Register result = locs()->out(0).reg();
// Push the result place holder initialized to NULL.
@@ -796,7 +797,7 @@ void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
uword entry;
const intptr_t argc_tag = NativeArguments::ComputeArgcTag(function());
const bool is_leaf_call =
(argc_tag & NativeArguments::AutoSetupScopeMask()) == 0;
(argc_tag & NativeArguments::AutoSetupScopeMask()) == 0;
const StubEntry* stub_entry;
if (link_lazily()) {
stub_entry = StubCode::CallBootstrapCFunction_entry();
+1
View File
@@ -818,6 +818,7 @@ LocationSummary* NativeCallInstr::MakeLocationSummary(Zone* zone,
void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
SetupNative();
Register result = locs()->out(0).reg();
const intptr_t argc_tag = NativeArguments::ComputeArgcTag(function());
const bool is_leaf_call =
+2 -1
View File
@@ -975,6 +975,7 @@ LocationSummary* NativeCallInstr::MakeLocationSummary(Zone* zone,
void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
SetupNative();
__ Comment("NativeCallInstr");
Register result = locs()->out(0).reg();
@@ -993,7 +994,7 @@ void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
uword entry;
const intptr_t argc_tag = NativeArguments::ComputeArgcTag(function());
const bool is_leaf_call =
(argc_tag & NativeArguments::AutoSetupScopeMask()) == 0;
(argc_tag & NativeArguments::AutoSetupScopeMask()) == 0;
const StubEntry* stub_entry;
if (link_lazily()) {
stub_entry = StubCode::CallBootstrapCFunction_entry();
+2 -1
View File
@@ -772,10 +772,11 @@ LocationSummary* NativeCallInstr::MakeLocationSummary(Zone* zone,
void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
SetupNative();
Register result = locs()->out(0).reg();
const intptr_t argc_tag = NativeArguments::ComputeArgcTag(function());
const bool is_leaf_call =
(argc_tag & NativeArguments::AutoSetupScopeMask()) == 0;
(argc_tag & NativeArguments::AutoSetupScopeMask()) == 0;
// Push the result place holder initialized to NULL.
__ PushObject(Object::null_object());
+1 -1
View File
@@ -234,7 +234,7 @@ void NativeEntry::LinkNativeCall(Dart_NativeArguments args) {
const intptr_t argc_tag = NativeArguments::ComputeArgcTag(func);
const bool is_leaf_call =
(argc_tag & NativeArguments::AutoSetupScopeMask()) == 0;
(argc_tag & NativeArguments::AutoSetupScopeMask()) == 0;
call_through_wrapper = !is_bootstrap_native && !is_leaf_call;
+1 -20
View File
@@ -7339,39 +7339,20 @@ void Parser::AddFormalParamsToScope(const ParamList* params,
void Parser::ParseNativeFunctionBlock(const ParamList* params,
const Function& func) {
ASSERT(func.is_native());
TRACE_PARSER("ParseNativeFunctionBlock");
const Class& cls = Class::Handle(Z, func.Owner());
const Library& library = Library::Handle(Z, cls.library());
ASSERT(func.NumParameters() == params->parameters->length());
TRACE_PARSER("ParseNativeFunctionBlock");
// Parse the function name out.
const intptr_t native_pos = TokenPos();
const String& native_name = ParseNativeDeclaration();
// Now resolve the native function to the corresponding native entrypoint.
const int num_params = NativeArguments::ParameterCountForResolution(func);
bool auto_setup_scope = true;
NativeFunction native_function = NativeEntry::ResolveNative(
library, native_name, num_params, &auto_setup_scope);
if (native_function == NULL) {
ReportError(native_pos,
"native function '%s' (%" Pd " arguments) cannot be found",
native_name.ToCString(), func.NumParameters());
}
func.SetIsNativeAutoSetupScope(auto_setup_scope);
// Now add the NativeBodyNode and return statement.
Dart_NativeEntryResolver resolver = library.native_entry_resolver();
bool is_bootstrap_native = Bootstrap::IsBootstapResolver(resolver);
current_block_->statements->Add(new(Z) ReturnNode(
TokenPos(),
new(Z) NativeBodyNode(
TokenPos(),
Function::ZoneHandle(Z, func.raw()),
native_name,
native_function,
current_block_->scope,
is_bootstrap_native,
FLAG_link_natives_lazily)));
}