| Index: vm/code_descriptors_test.cc
|
| ===================================================================
|
| --- vm/code_descriptors_test.cc (revision 6329)
|
| +++ vm/code_descriptors_test.cc (working copy)
|
| @@ -11,6 +11,7 @@
|
| #include "vm/code_descriptors.h"
|
| #include "vm/code_generator.h"
|
| #include "vm/dart_entry.h"
|
| +#include "vm/native_entry.h"
|
| #include "vm/unit_test.h"
|
|
|
| namespace dart {
|
| @@ -89,16 +90,16 @@
|
| // Validate the first stack map entry.
|
| stack_map ^= stack_map_list.At(0);
|
| EXPECT(stack_map.IsObject(0));
|
| - EXPECT_EQ(0, stack_map.Minimum());
|
| - EXPECT_EQ(0, stack_map.Maximum());
|
| + EXPECT_EQ(0, stack_map.MinimumBitOffset());
|
| + EXPECT_EQ(0, stack_map.MaximumBitOffset());
|
|
|
| // Validate the second stack map entry.
|
| stack_map ^= stack_map_list.At(1);
|
| EXPECT(stack_map.IsObject(0));
|
| EXPECT(!stack_map.IsObject(1));
|
| EXPECT(stack_map.IsObject(2));
|
| - EXPECT_EQ(0, stack_map.Minimum());
|
| - EXPECT_EQ(2, stack_map.Maximum());
|
| + EXPECT_EQ(0, stack_map.MinimumBitOffset());
|
| + EXPECT_EQ(2, stack_map.MaximumBitOffset());
|
|
|
| // Validate the third stack map entry.
|
| stack_map ^= stack_map_list.At(2);
|
| @@ -107,8 +108,8 @@
|
| for (intptr_t i = 2; i <= 5; i++) {
|
| EXPECT(stack_map.IsObject(i));
|
| }
|
| - EXPECT_EQ(0, stack_map.Minimum());
|
| - EXPECT_EQ(5, stack_map.Maximum());
|
| + EXPECT_EQ(0, stack_map.MinimumBitOffset());
|
| + EXPECT_EQ(5, stack_map.MaximumBitOffset());
|
|
|
| // Validate the fourth stack map entry.
|
| stack_map ^= stack_map_list.At(3);
|
| @@ -121,8 +122,8 @@
|
| EXPECT(!stack_map.IsObject(i));
|
| }
|
| EXPECT(stack_map.IsObject(10));
|
| - EXPECT_EQ(0, stack_map.Minimum());
|
| - EXPECT_EQ(10, stack_map.Maximum());
|
| + EXPECT_EQ(0, stack_map.MinimumBitOffset());
|
| + EXPECT_EQ(10, stack_map.MaximumBitOffset());
|
| retval = true;
|
| } else {
|
| retval = false;
|
| @@ -132,6 +133,86 @@
|
| }
|
| CODEGEN_TEST_RUN(StackmapCodegen, Smi::New(1))
|
|
|
| +
|
| +DEFINE_NATIVE_ENTRY(NativeFunc, 2) {
|
| + GET_NATIVE_ARGUMENT(Smi, i, arguments->At(0));
|
| + GET_NATIVE_ARGUMENT(Smi, k, arguments->At(1));
|
| + EXPECT_EQ(10, i.Value());
|
| + EXPECT_EQ(20, k.Value());
|
| + Isolate::Current()->heap()->CollectAllGarbage();
|
| +}
|
| +
|
| +
|
| +static Dart_NativeFunction native_resolver(Dart_Handle name,
|
| + int argument_count) {
|
| + return reinterpret_cast<Dart_NativeFunction>(&DN_NativeFunc);
|
| +}
|
| +
|
| +
|
| +TEST_CASE(StackmapGC) {
|
| + const char* kScriptChars =
|
| + "class A {"
|
| + " static void func(var i, var k) native 'NativeFunc';"
|
| + " static foo() {"
|
| + " var i;"
|
| + " var s1;"
|
| + " var k;"
|
| + " var s2;"
|
| + " var s3;"
|
| + " i = 10; s1 = 'abcd'; k = 20; s2 = 'B'; s3 = 'C';"
|
| + " func(i, k);"
|
| + " return i + k; }"
|
| + " static int moo() {"
|
| + " var i = A.foo();"
|
| + " Expect.equals(30, i);"
|
| + " }\n"
|
| + "}\n";
|
| + // First setup the script and compile the script.
|
| + TestCase::LoadTestScript(kScriptChars, native_resolver);
|
| + const String& name = String::Handle(String::New(TestCase::url()));
|
| + const Library& lib = Library::Handle(Library::LookupLibrary(name));
|
| + EXPECT(!lib.IsNull());
|
| + Class& cls = Class::Handle(
|
| + lib.LookupClass(String::Handle(String::NewSymbol("A"))));
|
| + EXPECT(!cls.IsNull());
|
| +
|
| + // Now compile the two functions 'A.foo' and 'A.moo'
|
| + String& function_moo_name = String::Handle(String::New("moo"));
|
| + Function& function_moo =
|
| + Function::Handle(cls.LookupStaticFunction(function_moo_name));
|
| + EXPECT(CompilerTest::TestCompileFunction(function_moo));
|
| + EXPECT(function_moo.HasCode());
|
| +
|
| + String& function_foo_name = String::Handle(String::New("foo"));
|
| + Function& function_foo =
|
| + Function::Handle(cls.LookupStaticFunction(function_foo_name));
|
| + EXPECT(CompilerTest::TestCompileFunction(function_foo));
|
| + EXPECT(function_foo.HasCode());
|
| +
|
| + // Build and setup a stackmap for function 'A.foo' in order to test the
|
| + // traversal of stack maps when a GC happens.
|
| + StackmapBuilder* builder = new StackmapBuilder();
|
| + EXPECT(builder != NULL);
|
| + builder->SetSlotAsValue(0); // var i.
|
| + builder->SetSlotAsObject(1); // var s1.
|
| + builder->SetSlotAsValue(2); // var k.
|
| + builder->SetSlotAsObject(3); // var s2.
|
| + builder->SetSlotAsObject(4); // var s3.
|
| + builder->AddEntry(0); // Add a stack map entry at pc offset 0.
|
| + const Code& code = Code::Handle(function_foo.unoptimized_code());
|
| + const Array& stack_maps = Array::Handle(builder->FinalizeStackmaps(code));
|
| + code.set_stackmaps(stack_maps);
|
| +
|
| + // Now invoke 'A.moo' and it will trigger a GC when the native function
|
| + // is called, this should then cause the stack map of function 'A.foo'
|
| + // to be traversed and the appropriate objects visited.
|
| + GrowableArray<const Object*> arguments;
|
| + const Array& kNoArgumentNames = Array::Handle();
|
| + Object& result = Object::Handle();
|
| + result = DartEntry::InvokeStatic(function_foo, arguments, kNoArgumentNames);
|
| + EXPECT(!result.IsError());
|
| +}
|
| +
|
| } // namespace dart
|
|
|
| #endif // defined TARGET_ARCH_IA32 || defined(TARGET_ARCH_X64)
|
|
|