| OLD | NEW | 
|    1 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file |    1 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file | 
|    2 // for details. All rights reserved. Use of this source code is governed by a |    2 // for details. All rights reserved. Use of this source code is governed by a | 
|    3 // BSD-style license that can be found in the LICENSE file. |    3 // BSD-style license that can be found in the LICENSE file. | 
|    4  |    4  | 
|    5 #include "platform/assert.h" |    5 #include "platform/assert.h" | 
|    6 #include "vm/globals.h" |    6 #include "vm/globals.h" | 
|    7 #if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64) |    7 #if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64) | 
|    8  |    8  | 
|    9 #include "vm/ast.h" |    9 #include "vm/ast.h" | 
|   10 #include "vm/assembler.h" |   10 #include "vm/assembler.h" | 
|   11 #include "vm/code_descriptors.h" |   11 #include "vm/code_descriptors.h" | 
|   12 #include "vm/code_generator.h" |   12 #include "vm/code_generator.h" | 
|   13 #include "vm/dart_entry.h" |   13 #include "vm/dart_entry.h" | 
 |   14 #include "vm/native_entry.h" | 
|   14 #include "vm/unit_test.h" |   15 #include "vm/unit_test.h" | 
|   15  |   16  | 
|   16 namespace dart { |   17 namespace dart { | 
|   17  |   18  | 
|   18 static const intptr_t kPos = Scanner::kDummyTokenIndex; |   19 static const intptr_t kPos = Scanner::kDummyTokenIndex; | 
|   19  |   20  | 
|   20  |   21  | 
|   21 CODEGEN_TEST_GENERATE(StackmapCodegen, test) { |   22 CODEGEN_TEST_GENERATE(StackmapCodegen, test) { | 
|   22   Assembler assembler; |   23   Assembler assembler; | 
|   23   const String& function_name = String::ZoneHandle(String::NewSymbol("test")); |   24   const String& function_name = String::ZoneHandle(String::NewSymbol("test")); | 
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   82     code.set_stackmaps(stack_maps); |   83     code.set_stackmaps(stack_maps); | 
|   83     function.SetCode(code); |   84     function.SetCode(code); | 
|   84     const Array& stack_map_list = Array::Handle(code.stackmaps()); |   85     const Array& stack_map_list = Array::Handle(code.stackmaps()); | 
|   85     EXPECT(!stack_map_list.IsNull()); |   86     EXPECT(!stack_map_list.IsNull()); | 
|   86     Stackmap& stack_map = Stackmap::Handle(); |   87     Stackmap& stack_map = Stackmap::Handle(); | 
|   87     EXPECT_EQ(4, stack_map_list.Length()); |   88     EXPECT_EQ(4, stack_map_list.Length()); | 
|   88  |   89  | 
|   89     // Validate the first stack map entry. |   90     // Validate the first stack map entry. | 
|   90     stack_map ^= stack_map_list.At(0); |   91     stack_map ^= stack_map_list.At(0); | 
|   91     EXPECT(stack_map.IsObject(0)); |   92     EXPECT(stack_map.IsObject(0)); | 
|   92     EXPECT_EQ(0, stack_map.Minimum()); |   93     EXPECT_EQ(0, stack_map.MinimumBitOffset()); | 
|   93     EXPECT_EQ(0, stack_map.Maximum()); |   94     EXPECT_EQ(0, stack_map.MaximumBitOffset()); | 
|   94  |   95  | 
|   95     // Validate the second stack map entry. |   96     // Validate the second stack map entry. | 
|   96     stack_map ^= stack_map_list.At(1); |   97     stack_map ^= stack_map_list.At(1); | 
|   97     EXPECT(stack_map.IsObject(0)); |   98     EXPECT(stack_map.IsObject(0)); | 
|   98     EXPECT(!stack_map.IsObject(1)); |   99     EXPECT(!stack_map.IsObject(1)); | 
|   99     EXPECT(stack_map.IsObject(2)); |  100     EXPECT(stack_map.IsObject(2)); | 
|  100     EXPECT_EQ(0, stack_map.Minimum()); |  101     EXPECT_EQ(0, stack_map.MinimumBitOffset()); | 
|  101     EXPECT_EQ(2, stack_map.Maximum()); |  102     EXPECT_EQ(2, stack_map.MaximumBitOffset()); | 
|  102  |  103  | 
|  103     // Validate the third stack map entry. |  104     // Validate the third stack map entry. | 
|  104     stack_map ^= stack_map_list.At(2); |  105     stack_map ^= stack_map_list.At(2); | 
|  105     EXPECT(stack_map.IsObject(0)); |  106     EXPECT(stack_map.IsObject(0)); | 
|  106     EXPECT(!stack_map.IsObject(1)); |  107     EXPECT(!stack_map.IsObject(1)); | 
|  107     for (intptr_t i = 2; i <= 5; i++) { |  108     for (intptr_t i = 2; i <= 5; i++) { | 
|  108       EXPECT(stack_map.IsObject(i)); |  109       EXPECT(stack_map.IsObject(i)); | 
|  109     } |  110     } | 
|  110     EXPECT_EQ(0, stack_map.Minimum()); |  111     EXPECT_EQ(0, stack_map.MinimumBitOffset()); | 
|  111     EXPECT_EQ(5, stack_map.Maximum()); |  112     EXPECT_EQ(5, stack_map.MaximumBitOffset()); | 
|  112  |  113  | 
|  113     // Validate the fourth stack map entry. |  114     // Validate the fourth stack map entry. | 
|  114     stack_map ^= stack_map_list.At(3); |  115     stack_map ^= stack_map_list.At(3); | 
|  115     EXPECT(stack_map.IsObject(0)); |  116     EXPECT(stack_map.IsObject(0)); | 
|  116     EXPECT(!stack_map.IsObject(1)); |  117     EXPECT(!stack_map.IsObject(1)); | 
|  117     for (intptr_t i = 2; i <= 5; i++) { |  118     for (intptr_t i = 2; i <= 5; i++) { | 
|  118       EXPECT(stack_map.IsObject(i)); |  119       EXPECT(stack_map.IsObject(i)); | 
|  119     } |  120     } | 
|  120     for (intptr_t i = 6; i <= 9; i++) { |  121     for (intptr_t i = 6; i <= 9; i++) { | 
|  121       EXPECT(!stack_map.IsObject(i)); |  122       EXPECT(!stack_map.IsObject(i)); | 
|  122     } |  123     } | 
|  123     EXPECT(stack_map.IsObject(10)); |  124     EXPECT(stack_map.IsObject(10)); | 
|  124     EXPECT_EQ(0, stack_map.Minimum()); |  125     EXPECT_EQ(0, stack_map.MinimumBitOffset()); | 
|  125     EXPECT_EQ(10, stack_map.Maximum()); |  126     EXPECT_EQ(10, stack_map.MaximumBitOffset()); | 
|  126     retval = true; |  127     retval = true; | 
|  127   } else { |  128   } else { | 
|  128     retval = false; |  129     retval = false; | 
|  129   } |  130   } | 
|  130   EXPECT(retval); |  131   EXPECT(retval); | 
|  131   isolate->set_long_jump_base(base); |  132   isolate->set_long_jump_base(base); | 
|  132 } |  133 } | 
|  133 CODEGEN_TEST_RUN(StackmapCodegen, Smi::New(1)) |  134 CODEGEN_TEST_RUN(StackmapCodegen, Smi::New(1)) | 
|  134  |  135  | 
 |  136  | 
 |  137 DEFINE_NATIVE_ENTRY(NativeFunc, 2) { | 
 |  138   GET_NATIVE_ARGUMENT(Smi, i, arguments->At(0)); | 
 |  139   GET_NATIVE_ARGUMENT(Smi, k, arguments->At(1)); | 
 |  140   EXPECT_EQ(10, i.Value()); | 
 |  141   EXPECT_EQ(20, k.Value()); | 
 |  142   Isolate::Current()->heap()->CollectAllGarbage(); | 
 |  143 } | 
 |  144  | 
 |  145  | 
 |  146 static Dart_NativeFunction native_resolver(Dart_Handle name, | 
 |  147                                            int argument_count) { | 
 |  148   return reinterpret_cast<Dart_NativeFunction>(&DN_NativeFunc); | 
 |  149 } | 
 |  150  | 
 |  151  | 
 |  152 TEST_CASE(StackmapGC) { | 
 |  153   const char* kScriptChars = | 
 |  154       "class A {" | 
 |  155       "  static void func(var i, var k) native 'NativeFunc';" | 
 |  156       "  static int foo() {" | 
 |  157       "    var i;" | 
 |  158       "    var s1;" | 
 |  159       "    var k;" | 
 |  160       "    var s2;" | 
 |  161       "    var s3;" | 
 |  162       "    i = 10; s1 = 'abcd'; k = 20; s2 = 'B'; s3 = 'C';" | 
 |  163       "    func(i, k);" | 
 |  164       "    return i + k; }" | 
 |  165       "  static int moo() {" | 
 |  166       "    var i = A.foo();" | 
 |  167       "    Expect.equals(30, i);" | 
 |  168       "  }\n" | 
 |  169       "}\n"; | 
 |  170   // First setup the script and compile the script. | 
 |  171   TestCase::LoadTestScript(kScriptChars, native_resolver); | 
 |  172   const String& name = String::Handle(String::New(TestCase::url())); | 
 |  173   const Library& lib = Library::Handle(Library::LookupLibrary(name)); | 
 |  174   EXPECT(!lib.IsNull()); | 
 |  175   Class& cls = Class::Handle( | 
 |  176       lib.LookupClass(String::Handle(String::NewSymbol("A")))); | 
 |  177   EXPECT(!cls.IsNull()); | 
 |  178  | 
 |  179   // Now compile the two functions 'A.foo' and 'A.moo' | 
 |  180   String& function_moo_name = String::Handle(String::New("moo")); | 
 |  181   Function& function_moo = | 
 |  182       Function::Handle(cls.LookupStaticFunction(function_moo_name)); | 
 |  183   EXPECT(CompilerTest::TestCompileFunction(function_moo)); | 
 |  184   EXPECT(function_moo.HasCode()); | 
 |  185  | 
 |  186   String& function_foo_name = String::Handle(String::New("foo")); | 
 |  187   Function& function_foo = | 
 |  188       Function::Handle(cls.LookupStaticFunction(function_foo_name)); | 
 |  189   EXPECT(CompilerTest::TestCompileFunction(function_foo)); | 
 |  190   EXPECT(function_foo.HasCode()); | 
 |  191  | 
 |  192   // Build and setup a stackmap for function 'A.foo' in order to test the | 
 |  193   // traversal of stack maps when a GC happens. | 
 |  194   StackmapBuilder* builder = new StackmapBuilder(); | 
 |  195   EXPECT(builder != NULL); | 
 |  196   builder->SetSlotAsValue(0);  // var i. | 
 |  197   builder->SetSlotAsObject(1);  // var s1. | 
 |  198   builder->SetSlotAsValue(2);  // var k. | 
 |  199   builder->SetSlotAsObject(3);  // var s2. | 
 |  200   builder->SetSlotAsObject(4);  // var s3. | 
 |  201   builder->AddEntry(0);  // Add a stack map entry at pc offset 0. | 
 |  202   const Code& code = Code::Handle(function_foo.unoptimized_code()); | 
 |  203   const Array& stack_maps = Array::Handle(builder->FinalizeStackmaps(code)); | 
 |  204   code.set_stackmaps(stack_maps); | 
 |  205  | 
 |  206   // Now invoke 'A.moo' and it will trigger a GC when the native function | 
 |  207   // is called, this should then cause the stack map of function 'A.foo' | 
 |  208   // to be traversed and the appropriate objects visited. | 
 |  209   GrowableArray<const Object*> arguments; | 
 |  210   const Array& kNoArgumentNames = Array::Handle(); | 
 |  211   Object& result = Object::Handle(); | 
 |  212   result = DartEntry::InvokeStatic(function_foo, arguments, kNoArgumentNames); | 
 |  213   EXPECT(!result.IsError()); | 
 |  214 } | 
 |  215  | 
|  135 }  // namespace dart |  216 }  // namespace dart | 
|  136  |  217  | 
|  137 #endif  // defined TARGET_ARCH_IA32 || defined(TARGET_ARCH_X64) |  218 #endif  // defined TARGET_ARCH_IA32 || defined(TARGET_ARCH_X64) | 
| OLD | NEW |