73bfbc5da4
- when resolving the native method which has been closurized account for the 'this' argument in the count of arguments. - explicitly copy the 'this' parameter in the closure context as the first parameter before calling the native function. This is done by piggy backing on the CopyParameters code used for functions with optional parameters. Review URL: https://chromiumcodereview.appspot.com//10535180 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@8816 260f80e4-7a28-3924-810f-c04153c831b5
509 lines
21 KiB
C++
509 lines
21 KiB
C++
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
#include "platform/assert.h"
|
|
#include "vm/globals.h"
|
|
#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64)
|
|
|
|
#include "vm/ast.h"
|
|
#include "vm/assembler.h"
|
|
#include "vm/class_finalizer.h"
|
|
#include "vm/code_generator.h"
|
|
#include "vm/compiler.h"
|
|
#include "vm/dart_entry.h"
|
|
#include "vm/native_entry.h"
|
|
#include "vm/native_entry_test.h"
|
|
#include "vm/unit_test.h"
|
|
#include "vm/virtual_memory.h"
|
|
|
|
namespace dart {
|
|
|
|
static const intptr_t kPos = Scanner::kDummyTokenIndex;
|
|
|
|
|
|
// Helper to allocate and return a LocalVariable.
|
|
static LocalVariable* NewTestLocalVariable(const char* name) {
|
|
const String& variable_name = String::ZoneHandle(String::New(name));
|
|
const Type& variable_type = Type::ZoneHandle(Type::DynamicType());
|
|
return new LocalVariable(kPos, variable_name, variable_type);
|
|
}
|
|
|
|
|
|
CODEGEN_TEST_GENERATE(SimpleReturnCodegen, test) {
|
|
test->node_sequence()->Add(new ReturnNode(kPos));
|
|
}
|
|
CODEGEN_TEST_RUN(SimpleReturnCodegen, Instance::null())
|
|
|
|
|
|
CODEGEN_TEST_GENERATE(SmiReturnCodegen, test) {
|
|
LiteralNode* l = new LiteralNode(kPos, Smi::ZoneHandle(Smi::New(3)));
|
|
test->node_sequence()->Add(new ReturnNode(kPos, l));
|
|
}
|
|
CODEGEN_TEST_RUN(SmiReturnCodegen, Smi::New(3))
|
|
|
|
|
|
CODEGEN_TEST2_GENERATE(SimpleStaticCallCodegen, function, test) {
|
|
// Wrap the SmiReturnCodegen test above as a static function and call it.
|
|
ArgumentListNode* no_arguments = new ArgumentListNode(kPos);
|
|
test->node_sequence()->Add(
|
|
new ReturnNode(kPos, new StaticCallNode(kPos, function, no_arguments)));
|
|
}
|
|
CODEGEN_TEST2_RUN(SimpleStaticCallCodegen, SmiReturnCodegen, Smi::New(3))
|
|
|
|
|
|
CODEGEN_TEST_GENERATE(ReturnParameterCodegen, test) {
|
|
SequenceNode* node_seq = test->node_sequence();
|
|
const int num_params = 1;
|
|
LocalVariable* parameter = NewTestLocalVariable("parameter");
|
|
LocalScope* local_scope = node_seq->scope();
|
|
local_scope->AddVariable(parameter);
|
|
ASSERT(local_scope->num_variables() == num_params);
|
|
const Function& function = test->function();
|
|
function.set_num_fixed_parameters(num_params);
|
|
ASSERT(function.num_optional_parameters() == 0);
|
|
node_seq->Add(new ReturnNode(kPos, new LoadLocalNode(kPos, *parameter)));
|
|
}
|
|
|
|
|
|
CODEGEN_TEST2_GENERATE(StaticCallReturnParameterCodegen, function, test) {
|
|
// Wrap and call the ReturnParameterCodegen test above as a static function.
|
|
SequenceNode* node_seq = test->node_sequence();
|
|
ArgumentListNode* arguments = new ArgumentListNode(kPos);
|
|
arguments->Add(new LiteralNode(kPos, Smi::ZoneHandle(Smi::New(3))));
|
|
node_seq->Add(new ReturnNode(kPos,
|
|
new StaticCallNode(kPos, function, arguments)));
|
|
}
|
|
CODEGEN_TEST2_RUN(StaticCallReturnParameterCodegen,
|
|
ReturnParameterCodegen,
|
|
Smi::New(3))
|
|
|
|
|
|
CODEGEN_TEST_GENERATE(SmiParamSumCodegen, test) {
|
|
SequenceNode* node_seq = test->node_sequence();
|
|
const int num_params = 2;
|
|
LocalVariable* param1 = NewTestLocalVariable("param1");
|
|
LocalVariable* param2 = NewTestLocalVariable("param2");
|
|
const int num_locals = 1;
|
|
LocalVariable* sum = NewTestLocalVariable("sum");
|
|
LocalScope* local_scope = node_seq->scope();
|
|
local_scope->AddVariable(param1);
|
|
local_scope->AddVariable(param2);
|
|
local_scope->AddVariable(sum);
|
|
ASSERT(local_scope->num_variables() == num_params + num_locals);
|
|
const Function& function = test->function();
|
|
function.set_num_fixed_parameters(num_params);
|
|
ASSERT(function.num_optional_parameters() == 0);
|
|
BinaryOpNode* add = new BinaryOpNode(kPos,
|
|
Token::kADD,
|
|
new LoadLocalNode(kPos, *param1),
|
|
new LoadLocalNode(kPos, *param2));
|
|
node_seq->Add(new StoreLocalNode(kPos, *sum, add));
|
|
node_seq->Add(new ReturnNode(kPos, new LoadLocalNode(kPos, *sum)));
|
|
}
|
|
|
|
|
|
CODEGEN_TEST2_GENERATE(StaticCallSmiParamSumCodegen, function, test) {
|
|
// Wrap and call the SmiParamSumCodegen test above as a static function.
|
|
SequenceNode* node_seq = test->node_sequence();
|
|
ArgumentListNode* arguments = new ArgumentListNode(kPos);
|
|
arguments->Add(new LiteralNode(kPos, Smi::ZoneHandle(Smi::New(3))));
|
|
arguments->Add(new LiteralNode(kPos, Smi::ZoneHandle(Smi::New(2))));
|
|
node_seq->Add(new ReturnNode(kPos,
|
|
new StaticCallNode(kPos, function, arguments)));
|
|
}
|
|
CODEGEN_TEST2_RUN(StaticCallSmiParamSumCodegen,
|
|
SmiParamSumCodegen,
|
|
Smi::New(5))
|
|
|
|
|
|
CODEGEN_TEST_GENERATE(SmiAddCodegen, test) {
|
|
SequenceNode* node_seq = test->node_sequence();
|
|
LiteralNode* a = new LiteralNode(kPos, Smi::ZoneHandle(Smi::New(3)));
|
|
LiteralNode* b = new LiteralNode(kPos, Smi::ZoneHandle(Smi::New(2)));
|
|
BinaryOpNode* add_node = new BinaryOpNode(kPos, Token::kADD, a, b);
|
|
node_seq->Add(new ReturnNode(kPos, add_node));
|
|
}
|
|
CODEGEN_TEST_RUN(SmiAddCodegen, Smi::New(5))
|
|
|
|
|
|
CODEGEN_TEST_GENERATE(GenericAddCodegen, test) {
|
|
SequenceNode* node_seq = test->node_sequence();
|
|
LiteralNode* a = new LiteralNode(kPos, Double::ZoneHandle(Double::New(12.2)));
|
|
LiteralNode* b = new LiteralNode(kPos, Smi::ZoneHandle(Smi::New(2)));
|
|
BinaryOpNode* add_node_1 = new BinaryOpNode(kPos, Token::kADD, a, b);
|
|
LiteralNode* c = new LiteralNode(kPos, Double::ZoneHandle(Double::New(0.8)));
|
|
BinaryOpNode* add_node_2 = new BinaryOpNode(kPos, Token::kADD, add_node_1, c);
|
|
node_seq->Add(new ReturnNode(kPos, add_node_2));
|
|
}
|
|
CODEGEN_TEST_RUN(GenericAddCodegen, Double::New(15.0))
|
|
|
|
|
|
CODEGEN_TEST_GENERATE(SmiBinaryOpCodegen, test) {
|
|
SequenceNode* node_seq = test->node_sequence();
|
|
LiteralNode* a = new LiteralNode(kPos, Smi::ZoneHandle(Smi::New(4)));
|
|
LiteralNode* b = new LiteralNode(kPos, Smi::ZoneHandle(Smi::New(2)));
|
|
LiteralNode* c = new LiteralNode(kPos, Smi::ZoneHandle(Smi::New(3)));
|
|
BinaryOpNode* sub_node =
|
|
new BinaryOpNode(kPos, Token::kSUB, a, b); // 4 - 2 -> 2.
|
|
BinaryOpNode* mul_node =
|
|
new BinaryOpNode(kPos, Token::kMUL, sub_node, c); // 2 * 3 -> 6.
|
|
BinaryOpNode* div_node =
|
|
new BinaryOpNode(kPos, Token::kTRUNCDIV, mul_node, b); // 6 ~/ 2 -> 3.
|
|
node_seq->Add(new ReturnNode(kPos, div_node));
|
|
}
|
|
CODEGEN_TEST_RUN(SmiBinaryOpCodegen, Smi::New(3))
|
|
|
|
|
|
CODEGEN_TEST_GENERATE(BoolNotCodegen, test) {
|
|
SequenceNode* node_seq = test->node_sequence();
|
|
const Bool& bool_false = Bool::ZoneHandle(Bool::False());
|
|
LiteralNode* b = new LiteralNode(kPos, bool_false);
|
|
UnaryOpNode* not_node = new UnaryOpNode(kPos, Token::kNOT, b);
|
|
node_seq->Add(new ReturnNode(kPos, not_node));
|
|
}
|
|
CODEGEN_TEST_RUN(BoolNotCodegen, Bool::True())
|
|
|
|
|
|
CODEGEN_TEST_GENERATE(BoolAndCodegen, test) {
|
|
SequenceNode* node_seq = test->node_sequence();
|
|
const Bool& bool_true = Bool::ZoneHandle(Bool::True());
|
|
const Bool& bool_false = Bool::ZoneHandle(Bool::False());
|
|
LiteralNode* a = new LiteralNode(kPos, bool_true);
|
|
LiteralNode* b = new LiteralNode(kPos, bool_false);
|
|
BinaryOpNode* and_node = new BinaryOpNode(kPos, Token::kAND, a, b);
|
|
node_seq->Add(new ReturnNode(kPos, and_node));
|
|
}
|
|
CODEGEN_TEST_RUN(BoolAndCodegen, Bool::False())
|
|
|
|
|
|
CODEGEN_TEST_GENERATE(BinaryOpCodegen, test) {
|
|
SequenceNode* node_seq = test->node_sequence();
|
|
LiteralNode* a = new LiteralNode(kPos, Double::ZoneHandle(Double::New(12)));
|
|
LiteralNode* b = new LiteralNode(kPos, Smi::ZoneHandle(Smi::New(2)));
|
|
LiteralNode* c = new LiteralNode(kPos, Double::ZoneHandle(Double::New(0.5)));
|
|
BinaryOpNode* sub_node = new BinaryOpNode(kPos, Token::kSUB, a, b);
|
|
BinaryOpNode* mul_node = new BinaryOpNode(kPos, Token::kMUL, sub_node, c);
|
|
BinaryOpNode* div_node = new BinaryOpNode(kPos, Token::kDIV, mul_node, b);
|
|
node_seq->Add(new ReturnNode(kPos, div_node));
|
|
}
|
|
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->AddVariable(NewTestLocalVariable("a"));
|
|
local_scope->AddVariable(NewTestLocalVariable("b"));
|
|
ASSERT(local_scope->num_variables() == num_params);
|
|
const Array& default_values = Array::ZoneHandle(Array::New(num_opt_params));
|
|
default_values.SetAt(0, Smi::ZoneHandle(Smi::New(1))); // b = 1.
|
|
test->set_default_parameter_values(default_values);
|
|
const Function& function = test->function();
|
|
function.set_num_fixed_parameters(num_fixed_params);
|
|
function.set_num_optional_parameters(num_opt_params);
|
|
const bool has_opt_params = true;
|
|
const String& native_name =
|
|
String::ZoneHandle(String::NewSymbol("TestSmiSub"));
|
|
NativeFunction native_function =
|
|
reinterpret_cast<NativeFunction>(NATIVE_ENTRY_FUNCTION(TestSmiSub));
|
|
node_seq->Add(new ReturnNode(kPos,
|
|
new NativeBodyNode(kPos,
|
|
native_name,
|
|
native_function,
|
|
num_params,
|
|
has_opt_params,
|
|
false)));
|
|
}
|
|
|
|
|
|
// 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)));
|
|
UnaryOpNode* neg_node = new UnaryOpNode(kPos, Token::kSUB, a);
|
|
node_seq->Add(new ReturnNode(kPos, neg_node));
|
|
}
|
|
CODEGEN_TEST_RUN(SmiUnaryOpCodegen, Smi::New(-12))
|
|
|
|
|
|
CODEGEN_TEST_GENERATE(DoubleUnaryOpCodegen, test) {
|
|
SequenceNode* node_seq = test->node_sequence();
|
|
LiteralNode* a = new LiteralNode(kPos, Double::ZoneHandle(Double::New(12.0)));
|
|
UnaryOpNode* neg_node = new UnaryOpNode(kPos, Token::kSUB, a);
|
|
node_seq->Add(new ReturnNode(kPos, neg_node));
|
|
}
|
|
CODEGEN_TEST_RUN(DoubleUnaryOpCodegen, Double::New(-12.0))
|
|
|
|
|
|
static Library& MakeTestLibrary(const char* url) {
|
|
const String& lib_url = String::ZoneHandle(String::NewSymbol(url));
|
|
Library& lib = Library::ZoneHandle(Library::New(lib_url));
|
|
lib.Register();
|
|
return lib;
|
|
}
|
|
|
|
|
|
static RawClass* LookupClass(const Library& lib, const char* name) {
|
|
const String& cls_name = String::ZoneHandle(String::NewSymbol(name));
|
|
return lib.LookupClass(cls_name);
|
|
}
|
|
|
|
|
|
CODEGEN_TEST_GENERATE(StaticCallCodegen, test) {
|
|
const char* kScriptChars =
|
|
"class A {\n"
|
|
" static bar() { return 42; }\n"
|
|
" static fly() { return 5; }\n"
|
|
"}\n";
|
|
|
|
String& url = String::Handle(String::New("dart-test:CompileScript"));
|
|
String& source = String::Handle(String::New(kScriptChars));
|
|
Script& script = Script::Handle(Script::New(url, source, RawScript::kSource));
|
|
Library& lib = MakeTestLibrary("TestLib");
|
|
EXPECT(CompilerTest::TestCompileScript(lib, script));
|
|
EXPECT(ClassFinalizer::FinalizePendingClasses());
|
|
Class& cls = Class::Handle(LookupClass(lib, "A"));
|
|
EXPECT(!cls.IsNull());
|
|
|
|
// 'bar' will not be compiled.
|
|
String& function_bar_name = String::Handle(String::New("bar"));
|
|
Function& function_bar =
|
|
Function::ZoneHandle(cls.LookupStaticFunction(function_bar_name));
|
|
EXPECT(!function_bar.IsNull());
|
|
EXPECT(!function_bar.HasCode());
|
|
|
|
// 'fly' will be compiled.
|
|
String& function_fly_name = String::Handle(String::New("fly"));
|
|
Function& function_fly =
|
|
Function::ZoneHandle(cls.LookupStaticFunction(function_fly_name));
|
|
EXPECT(!function_fly.IsNull());
|
|
EXPECT(CompilerTest::TestCompileFunction(function_fly));
|
|
EXPECT(function_fly.HasCode());
|
|
|
|
ArgumentListNode* no_arguments = new ArgumentListNode(kPos);
|
|
StaticCallNode* call_bar =
|
|
new StaticCallNode(kPos, function_bar, no_arguments);
|
|
StaticCallNode* call_fly =
|
|
new StaticCallNode(kPos, function_fly, no_arguments);
|
|
|
|
BinaryOpNode* add_node =
|
|
new BinaryOpNode(kPos, Token::kADD, call_bar, call_fly);
|
|
|
|
test->node_sequence()->Add(new ReturnNode(kPos, add_node));
|
|
}
|
|
CODEGEN_TEST_RUN(StaticCallCodegen, Smi::New(42 + 5))
|
|
|
|
|
|
CODEGEN_TEST_GENERATE(InstanceCallCodegen, test) {
|
|
const char* kScriptChars =
|
|
"class A {\n"
|
|
" A() {}\n"
|
|
" int bar() { return 42; }\n"
|
|
"}\n";
|
|
|
|
String& url = String::Handle(String::New("dart-test:CompileScript"));
|
|
String& source = String::Handle(String::New(kScriptChars));
|
|
Script& script = Script::Handle(Script::New(url, source, RawScript::kSource));
|
|
Library& lib = MakeTestLibrary("TestLib");
|
|
EXPECT(CompilerTest::TestCompileScript(lib, script));
|
|
EXPECT(ClassFinalizer::FinalizePendingClasses());
|
|
Class& cls = Class::ZoneHandle(LookupClass(lib, "A"));
|
|
EXPECT(!cls.IsNull());
|
|
|
|
String& constructor_name = String::Handle(String::New("A."));
|
|
Function& constructor =
|
|
Function::ZoneHandle(cls.LookupConstructor(constructor_name));
|
|
EXPECT(!constructor.IsNull());
|
|
|
|
// The unit test creates an instance of class A and calls function 'bar'.
|
|
String& function_bar_name = String::ZoneHandle(String::NewSymbol("bar"));
|
|
ArgumentListNode* no_arguments = new ArgumentListNode(kPos);
|
|
const TypeArguments& no_type_arguments = TypeArguments::ZoneHandle();
|
|
const LocalVariable& allocated = *test->CreateTempConstVariable("alloc");
|
|
InstanceCallNode* call_bar = new InstanceCallNode(
|
|
kPos,
|
|
new ConstructorCallNode(
|
|
kPos, no_type_arguments, constructor, no_arguments, allocated),
|
|
function_bar_name,
|
|
no_arguments);
|
|
|
|
test->node_sequence()->Add(new ReturnNode(kPos, call_bar));
|
|
}
|
|
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->AddVariable(NewTestLocalVariable("a"));
|
|
local_scope->AddVariable(NewTestLocalVariable("b"));
|
|
local_scope->AddVariable(NewTestLocalVariable("c"));
|
|
local_scope->AddVariable(NewTestLocalVariable("d"));
|
|
local_scope->AddVariable(NewTestLocalVariable("e"));
|
|
ASSERT(local_scope->num_variables() == num_params);
|
|
const Array& default_values = Array::ZoneHandle(Array::New(num_opt_params));
|
|
default_values.SetAt(0, Smi::ZoneHandle(Smi::New(10)));
|
|
default_values.SetAt(1, Smi::ZoneHandle(Smi::New(21)));
|
|
default_values.SetAt(2, Smi::ZoneHandle(Smi::New(-32)));
|
|
test->set_default_parameter_values(default_values);
|
|
const Function& function = test->function();
|
|
function.set_num_fixed_parameters(num_fixed_params);
|
|
function.set_num_optional_parameters(num_opt_params);
|
|
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 - 1; i++) {
|
|
function.SetParameterTypeAt(i, param_type);
|
|
}
|
|
const bool has_opt_params = true;
|
|
const String& native_name =
|
|
String::ZoneHandle(String::NewSymbol("TestSmiSum"));
|
|
NativeFunction native_function =
|
|
reinterpret_cast<NativeFunction>(NATIVE_ENTRY_FUNCTION(TestSmiSum));
|
|
node_seq->Add(new ReturnNode(kPos,
|
|
new NativeBodyNode(kPos,
|
|
native_name,
|
|
native_function,
|
|
num_params,
|
|
has_opt_params,
|
|
false)));
|
|
}
|
|
|
|
|
|
// 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))
|
|
|
|
|
|
// Test allocation of dart objects.
|
|
CODEGEN_TEST_GENERATE(AllocateNewObjectCodegen, test) {
|
|
const char* kScriptChars =
|
|
"class A {\n"
|
|
" A() {}\n"
|
|
" static bar() { return 42; }\n"
|
|
"}\n";
|
|
|
|
String& url = String::Handle(String::New("dart-test:CompileScript"));
|
|
String& source = String::Handle(String::New(kScriptChars));
|
|
Script& script = Script::Handle(Script::New(url, source, RawScript::kSource));
|
|
Library& lib = MakeTestLibrary("TestLib");
|
|
EXPECT(CompilerTest::TestCompileScript(lib, script));
|
|
EXPECT(ClassFinalizer::FinalizePendingClasses());
|
|
Class& cls = Class::ZoneHandle(LookupClass(lib, "A"));
|
|
EXPECT(!cls.IsNull());
|
|
|
|
String& constructor_name = String::Handle(String::New("A."));
|
|
Function& constructor =
|
|
Function::ZoneHandle(cls.LookupConstructor(constructor_name));
|
|
EXPECT(!constructor.IsNull());
|
|
|
|
const TypeArguments& no_type_arguments = TypeArguments::ZoneHandle();
|
|
ArgumentListNode* no_arguments = new ArgumentListNode(kPos);
|
|
const LocalVariable& allocated = *test->CreateTempConstVariable("alloc");
|
|
test->node_sequence()->Add(new ReturnNode(kPos, new ConstructorCallNode(
|
|
kPos, no_type_arguments, constructor, no_arguments, allocated)));
|
|
}
|
|
|
|
|
|
CODEGEN_TEST_RAW_RUN(AllocateNewObjectCodegen, function) {
|
|
GrowableArray<const Object*> arguments;
|
|
const Array& kNoArgumentNames = Array::Handle();
|
|
Object& result = Object::Handle();
|
|
result = DartEntry::InvokeStatic(function, arguments, kNoArgumentNames);
|
|
EXPECT(!result.IsError());
|
|
const GrowableObjectArray& libs = GrowableObjectArray::Handle(
|
|
Isolate::Current()->object_store()->libraries());
|
|
ASSERT(!libs.IsNull());
|
|
// App lib is the last one that was loaded.
|
|
intptr_t num_libs = libs.Length();
|
|
Library& app_lib = Library::Handle();
|
|
app_lib ^= libs.At(num_libs - 1);
|
|
ASSERT(!app_lib.IsNull());
|
|
const Class& cls = Class::Handle(
|
|
app_lib.LookupClass(String::Handle(String::NewSymbol("A"))));
|
|
EXPECT_EQ(cls.raw(), result.clazz());
|
|
}
|
|
|
|
} // namespace dart
|
|
|
|
#endif // defined TARGET_ARCH_IA32 || defined(TARGET_ARCH_X64)
|