d372a816bb
Remove code passing captured receiver to native instance closures; instead, access captured receiver in context, as non-native functions do. Review URL: https://codereview.chromium.org//11360116 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@14698 260f80e4-7a28-3924-810f-c04153c831b5
522 lines
21 KiB
C++
522 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/symbols.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(Symbols::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.HasOptionalParameters());
|
|
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.HasOptionalParameters());
|
|
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, Heap::kOld)));
|
|
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, Heap::kOld)));
|
|
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, Heap::kOld)));
|
|
LiteralNode* b = new LiteralNode(kPos, Smi::ZoneHandle(Smi::New(2)));
|
|
LiteralNode* c =
|
|
new LiteralNode(kPos, Double::ZoneHandle(Double::New(0.5, Heap::kOld)));
|
|
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_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)));
|
|
}
|
|
|
|
|
|
// 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::kNEGATE, 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, Heap::kOld)));
|
|
UnaryOpNode* neg_node = new UnaryOpNode(kPos, Token::kNEGATE, 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(Symbols::New(url));
|
|
Library& lib = Library::ZoneHandle(Library::New(lib_url));
|
|
lib.Register();
|
|
Library& core_lib = Library::Handle(Library::CoreLibrary());
|
|
ASSERT(!core_lib.IsNull());
|
|
const Namespace& core_ns = Namespace::Handle(
|
|
Namespace::New(core_lib, Array::Handle(), Array::Handle()));
|
|
lib.AddImport(core_ns);
|
|
return lib;
|
|
}
|
|
|
|
|
|
static RawClass* LookupClass(const Library& lib, const char* name) {
|
|
const String& cls_name = String::ZoneHandle(Symbols::New(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::kSourceTag));
|
|
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::kSourceTag));
|
|
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(Symbols::New("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_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 - 1; 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)));
|
|
}
|
|
|
|
|
|
// 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::kSourceTag));
|
|
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(Symbols::New("A"))));
|
|
EXPECT_EQ(cls.raw(), result.clazz());
|
|
}
|
|
|
|
} // namespace dart
|
|
|
|
#endif // defined TARGET_ARCH_IA32 || defined(TARGET_ARCH_X64)
|