Files
sdk/runtime/vm/compiler_test.cc
T
Florian Schneider 8d38a58c18 Make array allocation stub shared between isolates.
This allows to make the last explicitly named stubs shared between isolates.

When sharing code stubs, we can't do patching at their entry anymore.
Therefore, I had to remove patching support of the array allocation stub.
Is this a functionality we want to keep?

The change is mostly performance-neutral because optimized code has an inlined fast
path for array allocation and only uses the stub for the slow-case.

The only isolate-specific stubs left are object allocation stubs which are
associated with their Class are per-isolate.

Since this CL removes any isolate-specific stubs from StubCode, it becomes AllStatic.

BUG=
R=koda@google.com

Review URL: https://codereview.chromium.org//1247783002 .
2015-07-23 12:56:16 +02:00

187 lines
6.5 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/class_finalizer.h"
#include "vm/code_patcher.h"
#include "vm/compiler.h"
#include "vm/dart_api_impl.h"
#include "vm/object.h"
#include "vm/symbols.h"
#include "vm/unit_test.h"
namespace dart {
TEST_CASE(CompileScript) {
const char* kScriptChars =
"class A {\n"
" static foo() { 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::kScriptTag));
Library& lib = Library::Handle(Library::CoreLibrary());
EXPECT(CompilerTest::TestCompileScript(lib, script));
}
TEST_CASE(CompileFunction) {
const char* kScriptChars =
"class A {\n"
" static foo() { return 42; }\n"
" static moo() {\n"
" // A.foo();\n"
" }\n"
"}\n";
String& url = String::Handle(String::New("dart-test:CompileFunction"));
String& source = String::Handle(String::New(kScriptChars));
Script& script = Script::Handle(Script::New(url,
source,
RawScript::kScriptTag));
Library& lib = Library::Handle(Library::CoreLibrary());
EXPECT(CompilerTest::TestCompileScript(lib, script));
EXPECT(ClassFinalizer::ProcessPendingClasses());
Class& cls = Class::Handle(
lib.LookupClass(String::Handle(Symbols::New("A"))));
EXPECT(!cls.IsNull());
String& function_foo_name = String::Handle(String::New("foo"));
Function& function_foo =
Function::Handle(cls.LookupStaticFunction(function_foo_name));
EXPECT(!function_foo.IsNull());
String& function_source = String::Handle(function_foo.GetSource());
EXPECT_STREQ("static foo() { return 42; }", function_source.ToCString());
EXPECT(CompilerTest::TestCompileFunction(function_foo));
EXPECT(function_foo.HasCode());
String& function_moo_name = String::Handle(String::New("moo"));
Function& function_moo =
Function::Handle(cls.LookupStaticFunction(function_moo_name));
EXPECT(!function_moo.IsNull());
EXPECT(CompilerTest::TestCompileFunction(function_moo));
EXPECT(function_moo.HasCode());
function_source = function_moo.GetSource();
EXPECT_STREQ("static moo() {\n // A.foo();\n }",
function_source.ToCString());
}
TEST_CASE(RegenerateAllocStubs) {
const char* kScriptChars =
"class A {\n"
"}\n"
"unOpt() => new A(); \n"
"optIt() => new A(); \n"
"A main() {\n"
" return unOpt();\n"
"}\n";
// Isolate::Current()->flags().set_checked(true);
Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
EXPECT_VALID(result);
RawLibrary* raw_library = Library::RawCast(Api::UnwrapHandle(lib));
Library& lib_handle = Library::ZoneHandle(raw_library);
Class& cls = Class::Handle(
lib_handle.LookupClass(String::Handle(Symbols::New("A"))));
EXPECT(!cls.IsNull());
Isolate* isolate = Isolate::Current();
const Code& stub = Code::Handle(isolate,
StubCode::GetAllocationStubForClass(cls));
Class& owner = Class::Handle();
owner ^= stub.owner();
owner.DisableAllocationStub();
result = Dart_Invoke(lib, NewString("main"), 0, NULL);
EXPECT_VALID(result);
owner.DisableAllocationStub();
result = Dart_Invoke(lib, NewString("main"), 0, NULL);
EXPECT_VALID(result);
owner.DisableAllocationStub();
result = Dart_Invoke(lib, NewString("main"), 0, NULL);
EXPECT_VALID(result);
}
TEST_CASE(EvalExpression) {
const char* kScriptChars =
"int ten = 2 * 5; \n"
"get dot => '.'; \n"
"class A { \n"
" var apa = 'Herr Nilsson'; \n"
" calc(x) => '${x*ten}'; \n"
"} \n"
"makeObj() => new A(); \n";
Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
Dart_Handle obj_handle =
Dart_Invoke(lib, Dart_NewStringFromCString("makeObj"), 0, NULL);
EXPECT(!Dart_IsNull(obj_handle));
EXPECT(!Dart_IsError(obj_handle));
const Object& obj = Object::Handle(Api::UnwrapHandle(obj_handle));
EXPECT(!obj.IsNull());
EXPECT(obj.IsInstance());
String& expr_text = String::Handle();
expr_text = String::New("apa + ' ${calc(10)}' + dot");
Object& val = Object::Handle();
val = Instance::Cast(obj).Evaluate(expr_text,
Array::empty_array(),
Array::empty_array());
EXPECT(!val.IsNull());
EXPECT(!val.IsError());
EXPECT(val.IsString());
EXPECT_STREQ("Herr Nilsson 100.", val.ToCString());
}
TEST_CASE(EvalExpressionWithLazyCompile) {
Library& lib = Library::Handle(Library::CoreLibrary());
const String& expression = String::Handle(String::New(
"(){ return (){ return (){ return 3 + 4; }(); }(); }()"));
Object& val = Object::Handle();
val = lib.Evaluate(expression, Array::empty_array(), Array::empty_array());
EXPECT(!val.IsNull());
EXPECT(!val.IsError());
EXPECT(val.IsInteger());
EXPECT_EQ(7, Integer::Cast(val).AsInt64Value());
}
TEST_CASE(EvalExpressionExhaustCIDs) {
Library& lib = Library::Handle(Library::CoreLibrary());
const String& expression = String::Handle(String::New("3 + 4"));
Object& val = Object::Handle();
// Run once to ensure everything we touch is compiled.
val = lib.Evaluate(expression, Array::empty_array(), Array::empty_array());
EXPECT(!val.IsNull());
EXPECT(!val.IsError());
EXPECT(val.IsInteger());
EXPECT_EQ(7, Integer::Cast(val).AsInt64Value());
intptr_t initial_class_table_size =
Isolate::Current()->class_table()->NumCids();
val = lib.Evaluate(expression, Array::empty_array(), Array::empty_array());
EXPECT(!val.IsNull());
EXPECT(!val.IsError());
EXPECT(val.IsInteger());
EXPECT_EQ(7, Integer::Cast(val).AsInt64Value());
intptr_t final_class_table_size =
Isolate::Current()->class_table()->NumCids();
// Eval should not eat into this non-renewable resource.
EXPECT_EQ(initial_class_table_size, final_class_table_size);
}
} // namespace dart