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 | 7 |
8 #include "vm/ast.h" | 8 #include "vm/ast.h" |
9 #include "vm/assembler.h" | 9 #include "vm/assembler.h" |
10 #include "vm/code_descriptors.h" | 10 #include "vm/code_descriptors.h" |
11 #include "vm/compiler.h" | 11 #include "vm/compiler.h" |
12 #include "vm/dart_entry.h" | 12 #include "vm/dart_entry.h" |
13 #include "vm/native_entry.h" | 13 #include "vm/native_entry.h" |
14 #include "vm/parser.h" | 14 #include "vm/parser.h" |
15 #include "vm/symbols.h" | 15 #include "vm/symbols.h" |
16 #include "vm/thread.h" | 16 #include "vm/thread.h" |
17 #include "vm/unit_test.h" | 17 #include "vm/unit_test.h" |
18 | 18 |
19 namespace dart { | 19 namespace dart { |
20 | 20 |
21 static const TokenPosition kPos = TokenPosition::kNoSource; | 21 static const TokenPosition kPos = TokenPosition::kNoSource; |
22 | 22 |
23 | 23 |
24 CODEGEN_TEST_GENERATE(StackmapCodegen, test) { | 24 CODEGEN_TEST_GENERATE(StackMapCodegen, test) { |
25 ParsedFunction* parsed_function = | 25 ParsedFunction* parsed_function = |
26 new ParsedFunction(Thread::Current(), test->function()); | 26 new ParsedFunction(Thread::Current(), test->function()); |
27 LiteralNode* l = new LiteralNode(kPos, Smi::ZoneHandle(Smi::New(1))); | 27 LiteralNode* l = new LiteralNode(kPos, Smi::ZoneHandle(Smi::New(1))); |
28 test->node_sequence()->Add(new ReturnNode(kPos, l)); | 28 test->node_sequence()->Add(new ReturnNode(kPos, l)); |
29 l = new LiteralNode(kPos, Smi::ZoneHandle(Smi::New(2))); | 29 l = new LiteralNode(kPos, Smi::ZoneHandle(Smi::New(2))); |
30 test->node_sequence()->Add(new ReturnNode(kPos, l)); | 30 test->node_sequence()->Add(new ReturnNode(kPos, l)); |
31 l = new LiteralNode(kPos, Smi::ZoneHandle(Smi::New(3))); | 31 l = new LiteralNode(kPos, Smi::ZoneHandle(Smi::New(3))); |
32 test->node_sequence()->Add(new ReturnNode(kPos, l)); | 32 test->node_sequence()->Add(new ReturnNode(kPos, l)); |
33 parsed_function->SetNodeSequence(test->node_sequence()); | 33 parsed_function->SetNodeSequence(test->node_sequence()); |
34 parsed_function->set_instantiator(NULL); | 34 parsed_function->set_instantiator(NULL); |
35 parsed_function->EnsureExpressionTemp(); | 35 parsed_function->EnsureExpressionTemp(); |
36 test->node_sequence()->scope()->AddVariable( | 36 test->node_sequence()->scope()->AddVariable( |
37 parsed_function->expression_temp_var()); | 37 parsed_function->expression_temp_var()); |
38 test->node_sequence()->scope()->AddVariable( | 38 test->node_sequence()->scope()->AddVariable( |
39 parsed_function->current_context_var()); | 39 parsed_function->current_context_var()); |
40 parsed_function->AllocateVariables(); | 40 parsed_function->AllocateVariables(); |
41 bool retval; | 41 bool retval; |
42 Isolate* isolate = Isolate::Current(); | 42 Isolate* isolate = Isolate::Current(); |
43 EXPECT(isolate != NULL); | 43 EXPECT(isolate != NULL); |
44 LongJumpScope jump; | 44 LongJumpScope jump; |
45 if (setjmp(*jump.Set()) == 0) { | 45 if (setjmp(*jump.Set()) == 0) { |
46 // Build a stackmap table and some stackmap table entries. | 46 // Build a stackmap table and some stackmap table entries. |
47 const intptr_t kStackSlotCount = 11; | 47 const intptr_t kStackSlotCount = 11; |
48 StackmapTableBuilder* stackmap_table_builder = new StackmapTableBuilder(); | 48 StackMapTableBuilder* stackmap_table_builder = new StackMapTableBuilder(); |
49 EXPECT(stackmap_table_builder != NULL); | 49 EXPECT(stackmap_table_builder != NULL); |
50 | 50 |
51 BitmapBuilder* stack_bitmap = new BitmapBuilder(); | 51 BitmapBuilder* stack_bitmap = new BitmapBuilder(); |
52 EXPECT(stack_bitmap != NULL); | 52 EXPECT(stack_bitmap != NULL); |
53 EXPECT_EQ(0, stack_bitmap->Length()); | 53 EXPECT_EQ(0, stack_bitmap->Length()); |
54 stack_bitmap->Set(0, true); | 54 stack_bitmap->Set(0, true); |
55 EXPECT_EQ(1, stack_bitmap->Length()); | 55 EXPECT_EQ(1, stack_bitmap->Length()); |
56 stack_bitmap->SetLength(kStackSlotCount); | 56 stack_bitmap->SetLength(kStackSlotCount); |
57 EXPECT_EQ(kStackSlotCount, stack_bitmap->Length()); | 57 EXPECT_EQ(kStackSlotCount, stack_bitmap->Length()); |
58 | 58 |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
118 } | 118 } |
119 // Add a stack map entry at pc offset 3. | 119 // Add a stack map entry at pc offset 3. |
120 stackmap_table_builder->AddEntry(3, stack_bitmap, 0); | 120 stackmap_table_builder->AddEntry(3, stack_bitmap, 0); |
121 | 121 |
122 const Error& error = | 122 const Error& error = |
123 Error::Handle(Compiler::CompileParsedFunction(parsed_function)); | 123 Error::Handle(Compiler::CompileParsedFunction(parsed_function)); |
124 EXPECT(error.IsNull()); | 124 EXPECT(error.IsNull()); |
125 const Code& code = Code::Handle(test->function().CurrentCode()); | 125 const Code& code = Code::Handle(test->function().CurrentCode()); |
126 | 126 |
127 const Array& stack_maps = | 127 const Array& stack_maps = |
128 Array::Handle(stackmap_table_builder->FinalizeStackmaps(code)); | 128 Array::Handle(stackmap_table_builder->FinalizeStackMaps(code)); |
129 code.set_stackmaps(stack_maps); | 129 code.set_stackmaps(stack_maps); |
130 const Array& stack_map_list = Array::Handle(code.stackmaps()); | 130 const Array& stack_map_list = Array::Handle(code.stackmaps()); |
131 EXPECT(!stack_map_list.IsNull()); | 131 EXPECT(!stack_map_list.IsNull()); |
132 Stackmap& stack_map = Stackmap::Handle(); | 132 StackMap& stack_map = StackMap::Handle(); |
133 EXPECT_EQ(4, stack_map_list.Length()); | 133 EXPECT_EQ(4, stack_map_list.Length()); |
134 | 134 |
135 // Validate the first stack map entry. | 135 // Validate the first stack map entry. |
136 stack_map ^= stack_map_list.At(0); | 136 stack_map ^= stack_map_list.At(0); |
137 EXPECT_EQ(kStackSlotCount, stack_map.Length()); | 137 EXPECT_EQ(kStackSlotCount, stack_map.Length()); |
138 for (intptr_t i = 0; i < kStackSlotCount; ++i) { | 138 for (intptr_t i = 0; i < kStackSlotCount; ++i) { |
139 EXPECT_EQ(expectation0[i], stack_map.IsObject(i)); | 139 EXPECT_EQ(expectation0[i], stack_map.IsObject(i)); |
140 } | 140 } |
141 | 141 |
142 // Validate the second stack map entry. | 142 // Validate the second stack map entry. |
(...skipping 15 matching lines...) Expand all Loading... |
158 EXPECT_EQ(kStackSlotCount, stack_map.Length()); | 158 EXPECT_EQ(kStackSlotCount, stack_map.Length()); |
159 for (intptr_t i = 0; i < kStackSlotCount; ++i) { | 159 for (intptr_t i = 0; i < kStackSlotCount; ++i) { |
160 EXPECT_EQ(expectation3[i], stack_map.IsObject(i)); | 160 EXPECT_EQ(expectation3[i], stack_map.IsObject(i)); |
161 } | 161 } |
162 retval = true; | 162 retval = true; |
163 } else { | 163 } else { |
164 retval = false; | 164 retval = false; |
165 } | 165 } |
166 EXPECT(retval); | 166 EXPECT(retval); |
167 } | 167 } |
168 CODEGEN_TEST_RUN(StackmapCodegen, Smi::New(1)) | 168 CODEGEN_TEST_RUN(StackMapCodegen, Smi::New(1)) |
169 | 169 |
170 | 170 |
171 static void NativeFunc(Dart_NativeArguments args) { | 171 static void NativeFunc(Dart_NativeArguments args) { |
172 Dart_Handle i = Dart_GetNativeArgument(args, 0); | 172 Dart_Handle i = Dart_GetNativeArgument(args, 0); |
173 Dart_Handle k = Dart_GetNativeArgument(args, 1); | 173 Dart_Handle k = Dart_GetNativeArgument(args, 1); |
174 int64_t value = -1; | 174 int64_t value = -1; |
175 EXPECT_VALID(Dart_IntegerToInt64(i, &value)); | 175 EXPECT_VALID(Dart_IntegerToInt64(i, &value)); |
176 EXPECT_EQ(10, value); | 176 EXPECT_EQ(10, value); |
177 EXPECT_VALID(Dart_IntegerToInt64(k, &value)); | 177 EXPECT_VALID(Dart_IntegerToInt64(k, &value)); |
178 EXPECT_EQ(20, value); | 178 EXPECT_EQ(20, value); |
179 { | 179 { |
180 TransitionNativeToVM transition(Thread::Current()); | 180 TransitionNativeToVM transition(Thread::Current()); |
181 Isolate::Current()->heap()->CollectAllGarbage(); | 181 Isolate::Current()->heap()->CollectAllGarbage(); |
182 } | 182 } |
183 } | 183 } |
184 | 184 |
185 | 185 |
186 static Dart_NativeFunction native_resolver(Dart_Handle name, | 186 static Dart_NativeFunction native_resolver(Dart_Handle name, |
187 int argument_count, | 187 int argument_count, |
188 bool* auto_setup_scope) { | 188 bool* auto_setup_scope) { |
189 ASSERT(auto_setup_scope); | 189 ASSERT(auto_setup_scope); |
190 *auto_setup_scope = false; | 190 *auto_setup_scope = false; |
191 return reinterpret_cast<Dart_NativeFunction>(&NativeFunc); | 191 return reinterpret_cast<Dart_NativeFunction>(&NativeFunc); |
192 } | 192 } |
193 | 193 |
194 | 194 |
195 TEST_CASE(StackmapGC) { | 195 TEST_CASE(StackMapGC) { |
196 const char* kScriptChars = | 196 const char* kScriptChars = |
197 "class A {" | 197 "class A {" |
198 " static void func(var i, var k) native 'NativeFunc';" | 198 " static void func(var i, var k) native 'NativeFunc';" |
199 " static foo() {" | 199 " static foo() {" |
200 " var i;" | 200 " var i;" |
201 " var s1;" | 201 " var s1;" |
202 " var k;" | 202 " var k;" |
203 " var s2;" | 203 " var s2;" |
204 " var s3;" | 204 " var s3;" |
205 " i = 10; s1 = 'abcd'; k = 20; s2 = 'B'; s3 = 'C';" | 205 " i = 10; s1 = 'abcd'; k = 20; s2 = 'B'; s3 = 'C';" |
(...skipping 24 matching lines...) Expand all Loading... |
230 EXPECT(function_moo.HasCode()); | 230 EXPECT(function_moo.HasCode()); |
231 | 231 |
232 String& function_foo_name = String::Handle(String::New("foo")); | 232 String& function_foo_name = String::Handle(String::New("foo")); |
233 Function& function_foo = | 233 Function& function_foo = |
234 Function::Handle(cls.LookupStaticFunction(function_foo_name)); | 234 Function::Handle(cls.LookupStaticFunction(function_foo_name)); |
235 EXPECT(CompilerTest::TestCompileFunction(function_foo)); | 235 EXPECT(CompilerTest::TestCompileFunction(function_foo)); |
236 EXPECT(function_foo.HasCode()); | 236 EXPECT(function_foo.HasCode()); |
237 | 237 |
238 // Build and setup a stackmap for the call to 'func' in 'A.foo' in order | 238 // Build and setup a stackmap for the call to 'func' in 'A.foo' in order |
239 // to test the traversal of stack maps when a GC happens. | 239 // to test the traversal of stack maps when a GC happens. |
240 StackmapTableBuilder* stackmap_table_builder = new StackmapTableBuilder(); | 240 StackMapTableBuilder* stackmap_table_builder = new StackMapTableBuilder(); |
241 EXPECT(stackmap_table_builder != NULL); | 241 EXPECT(stackmap_table_builder != NULL); |
242 BitmapBuilder* stack_bitmap = new BitmapBuilder(); | 242 BitmapBuilder* stack_bitmap = new BitmapBuilder(); |
243 EXPECT(stack_bitmap != NULL); | 243 EXPECT(stack_bitmap != NULL); |
244 stack_bitmap->Set(0, false); // var i. | 244 stack_bitmap->Set(0, false); // var i. |
245 stack_bitmap->Set(1, true); // var s1. | 245 stack_bitmap->Set(1, true); // var s1. |
246 stack_bitmap->Set(2, false); // var k. | 246 stack_bitmap->Set(2, false); // var k. |
247 stack_bitmap->Set(3, true); // var s2. | 247 stack_bitmap->Set(3, true); // var s2. |
248 stack_bitmap->Set(4, true); // var s3. | 248 stack_bitmap->Set(4, true); // var s3. |
249 const Code& code = Code::Handle(function_foo.unoptimized_code()); | 249 const Code& code = Code::Handle(function_foo.unoptimized_code()); |
250 // Search for the pc of the call to 'func'. | 250 // Search for the pc of the call to 'func'. |
251 const PcDescriptors& descriptors = | 251 const PcDescriptors& descriptors = |
252 PcDescriptors::Handle(code.pc_descriptors()); | 252 PcDescriptors::Handle(code.pc_descriptors()); |
253 int call_count = 0; | 253 int call_count = 0; |
254 PcDescriptors::Iterator iter(descriptors, RawPcDescriptors::kUnoptStaticCall); | 254 PcDescriptors::Iterator iter(descriptors, RawPcDescriptors::kUnoptStaticCall); |
255 while (iter.MoveNext()) { | 255 while (iter.MoveNext()) { |
256 stackmap_table_builder->AddEntry(iter.PcOffset(), stack_bitmap, 0); | 256 stackmap_table_builder->AddEntry(iter.PcOffset(), stack_bitmap, 0); |
257 ++call_count; | 257 ++call_count; |
258 } | 258 } |
259 // We can't easily check that we put the stackmap at the correct pc, but | 259 // We can't easily check that we put the stackmap at the correct pc, but |
260 // we did if there was exactly one call seen. | 260 // we did if there was exactly one call seen. |
261 EXPECT(call_count == 1); | 261 EXPECT(call_count == 1); |
262 const Array& stack_maps = | 262 const Array& stack_maps = |
263 Array::Handle(stackmap_table_builder->FinalizeStackmaps(code)); | 263 Array::Handle(stackmap_table_builder->FinalizeStackMaps(code)); |
264 code.set_stackmaps(stack_maps); | 264 code.set_stackmaps(stack_maps); |
265 | 265 |
266 // Now invoke 'A.moo' and it will trigger a GC when the native function | 266 // Now invoke 'A.moo' and it will trigger a GC when the native function |
267 // is called, this should then cause the stack map of function 'A.foo' | 267 // is called, this should then cause the stack map of function 'A.foo' |
268 // to be traversed and the appropriate objects visited. | 268 // to be traversed and the appropriate objects visited. |
269 const Object& result = Object::Handle( | 269 const Object& result = Object::Handle( |
270 DartEntry::InvokeFunction(function_foo, Object::empty_array())); | 270 DartEntry::InvokeFunction(function_foo, Object::empty_array())); |
271 EXPECT(!result.IsError()); | 271 EXPECT(!result.IsError()); |
272 } | 272 } |
273 | 273 |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
361 if (token_positions[i] != it.TokenPos().value()) { | 361 if (token_positions[i] != it.TokenPos().value()) { |
362 OS::Print("[%" Pd "]: Expected: %" Pd " != %" Pd "\n", i, | 362 OS::Print("[%" Pd "]: Expected: %" Pd " != %" Pd "\n", i, |
363 token_positions[i], it.TokenPos().value()); | 363 token_positions[i], it.TokenPos().value()); |
364 } | 364 } |
365 EXPECT(token_positions[i] == it.TokenPos().value()); | 365 EXPECT(token_positions[i] == it.TokenPos().value()); |
366 i++; | 366 i++; |
367 } | 367 } |
368 } | 368 } |
369 | 369 |
370 } // namespace dart | 370 } // namespace dart |
OLD | NEW |