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" |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
56 if (setjmp(*jump.Set()) == 0) { | 56 if (setjmp(*jump.Set()) == 0) { |
57 // Build some stack map entries. | 57 // Build some stack map entries. |
58 StackmapBuilder* builder = new StackmapBuilder(); | 58 StackmapBuilder* builder = new StackmapBuilder(); |
59 EXPECT(builder != NULL); | 59 EXPECT(builder != NULL); |
60 builder->SetSlotAsObject(0); | 60 builder->SetSlotAsObject(0); |
61 EXPECT(builder->IsSlotObject(0)); | 61 EXPECT(builder->IsSlotObject(0)); |
62 builder->AddEntry(0); // Add a stack map entry at pc offset 0. | 62 builder->AddEntry(0); // Add a stack map entry at pc offset 0. |
63 builder->SetSlotAsValue(1); | 63 builder->SetSlotAsValue(1); |
64 EXPECT(!builder->IsSlotObject(1)); | 64 EXPECT(!builder->IsSlotObject(1)); |
65 builder->SetSlotAsObject(2); | 65 builder->SetSlotAsObject(2); |
| 66 EXPECT(builder->IsSlotObject(2)); |
66 builder->AddEntry(1); // Add a stack map entry at pc offset 1. | 67 builder->AddEntry(1); // Add a stack map entry at pc offset 1. |
67 EXPECT(builder->IsSlotObject(2)); | |
68 builder->SetSlotRangeAsObject(3, 5); | 68 builder->SetSlotRangeAsObject(3, 5); |
69 for (intptr_t i = 3; i <= 5; i++) { | 69 for (intptr_t i = 3; i <= 5; i++) { |
70 EXPECT(builder->IsSlotObject(i)); | 70 EXPECT(builder->IsSlotObject(i)); |
71 } | 71 } |
72 builder->AddEntry(2); // Add a stack map entry at pc offset 2. | 72 builder->AddEntry(2); // Add a stack map entry at pc offset 2. |
73 builder->SetSlotRangeAsValue(6, 9); | 73 builder->SetSlotRangeAsValue(6, 9); |
74 for (intptr_t i = 6; i <= 9; i++) { | 74 for (intptr_t i = 6; i <= 9; i++) { |
75 EXPECT(!builder->IsSlotObject(i)); | 75 EXPECT(!builder->IsSlotObject(i)); |
76 } | 76 } |
77 builder->SetSlotAsObject(10); | 77 builder->SetSlotAsObject(10); |
| 78 EXPECT(builder->IsSlotObject(10)); |
78 builder->AddEntry(3); // Add a stack map entry at pc offset 3. | 79 builder->AddEntry(3); // Add a stack map entry at pc offset 3. |
79 | 80 |
80 const Error& error = | 81 const Error& error = |
81 Error::Handle(Compiler::CompileParsedFunction(parsed_function)); | 82 Error::Handle(Compiler::CompileParsedFunction(parsed_function)); |
82 EXPECT(error.IsNull()); | 83 EXPECT(error.IsNull()); |
83 const Code& code = Code::Handle(function.CurrentCode()); | 84 const Code& code = Code::Handle(function.CurrentCode()); |
84 | 85 |
85 const Array& stack_maps = Array::Handle(builder->FinalizeStackmaps(code)); | 86 const Array& stack_maps = Array::Handle(builder->FinalizeStackmaps(code)); |
86 code.set_stackmaps(stack_maps); | 87 code.set_stackmaps(stack_maps); |
87 const Array& stack_map_list = Array::Handle(code.stackmaps()); | 88 const Array& stack_map_list = Array::Handle(code.stackmaps()); |
88 EXPECT(!stack_map_list.IsNull()); | 89 EXPECT(!stack_map_list.IsNull()); |
89 Stackmap& stack_map = Stackmap::Handle(); | 90 Stackmap& stack_map = Stackmap::Handle(); |
90 EXPECT_EQ(4, stack_map_list.Length()); | 91 EXPECT_EQ(4, stack_map_list.Length()); |
91 | 92 |
92 // Validate the first stack map entry. | 93 // Validate the first stack map entry. |
93 stack_map ^= stack_map_list.At(0); | 94 stack_map ^= stack_map_list.At(0); |
94 EXPECT(stack_map.IsObject(0)); | 95 EXPECT(stack_map.IsObject(0)); |
95 EXPECT_EQ(0, stack_map.MinimumBitOffset()); | 96 EXPECT_EQ(0, stack_map.MinimumBitIndex()); |
96 EXPECT_EQ(0, stack_map.MaximumBitOffset()); | 97 EXPECT_EQ(0, stack_map.MaximumBitIndex()); |
97 | 98 |
98 // Validate the second stack map entry. | 99 // Validate the second stack map entry. |
99 stack_map ^= stack_map_list.At(1); | 100 stack_map ^= stack_map_list.At(1); |
100 EXPECT(stack_map.IsObject(0)); | 101 EXPECT(stack_map.IsObject(0)); |
101 EXPECT(!stack_map.IsObject(1)); | 102 EXPECT(!stack_map.IsObject(1)); |
102 EXPECT(stack_map.IsObject(2)); | 103 EXPECT(stack_map.IsObject(2)); |
103 EXPECT_EQ(0, stack_map.MinimumBitOffset()); | 104 EXPECT_EQ(0, stack_map.MinimumBitIndex()); |
104 EXPECT_EQ(2, stack_map.MaximumBitOffset()); | 105 EXPECT_EQ(2, stack_map.MaximumBitIndex()); |
105 | 106 |
106 // Validate the third stack map entry. | 107 // Validate the third stack map entry. |
107 stack_map ^= stack_map_list.At(2); | 108 stack_map ^= stack_map_list.At(2); |
108 EXPECT(stack_map.IsObject(0)); | 109 EXPECT(stack_map.IsObject(0)); |
109 EXPECT(!stack_map.IsObject(1)); | 110 EXPECT(!stack_map.IsObject(1)); |
110 for (intptr_t i = 2; i <= 5; i++) { | 111 for (intptr_t i = 2; i <= 5; i++) { |
111 EXPECT(stack_map.IsObject(i)); | 112 EXPECT(stack_map.IsObject(i)); |
112 } | 113 } |
113 EXPECT_EQ(0, stack_map.MinimumBitOffset()); | 114 EXPECT_EQ(0, stack_map.MinimumBitIndex()); |
114 EXPECT_EQ(5, stack_map.MaximumBitOffset()); | 115 EXPECT_EQ(5, stack_map.MaximumBitIndex()); |
115 | 116 |
116 // Validate the fourth stack map entry. | 117 // Validate the fourth stack map entry. |
117 stack_map ^= stack_map_list.At(3); | 118 stack_map ^= stack_map_list.At(3); |
118 EXPECT(stack_map.IsObject(0)); | 119 EXPECT(stack_map.IsObject(0)); |
119 EXPECT(!stack_map.IsObject(1)); | 120 EXPECT(!stack_map.IsObject(1)); |
120 for (intptr_t i = 2; i <= 5; i++) { | 121 for (intptr_t i = 2; i <= 5; i++) { |
121 EXPECT(stack_map.IsObject(i)); | 122 EXPECT(stack_map.IsObject(i)); |
122 } | 123 } |
123 for (intptr_t i = 6; i <= 9; i++) { | 124 for (intptr_t i = 6; i <= 9; i++) { |
124 EXPECT(!stack_map.IsObject(i)); | 125 EXPECT(!stack_map.IsObject(i)); |
125 } | 126 } |
126 EXPECT(stack_map.IsObject(10)); | 127 EXPECT(stack_map.IsObject(10)); |
127 EXPECT_EQ(0, stack_map.MinimumBitOffset()); | 128 EXPECT_EQ(0, stack_map.MinimumBitIndex()); |
128 EXPECT_EQ(10, stack_map.MaximumBitOffset()); | 129 EXPECT_EQ(10, stack_map.MaximumBitIndex()); |
129 retval = true; | 130 retval = true; |
130 } else { | 131 } else { |
131 retval = false; | 132 retval = false; |
132 } | 133 } |
133 EXPECT(retval); | 134 EXPECT(retval); |
134 isolate->set_long_jump_base(base); | 135 isolate->set_long_jump_base(base); |
135 } | 136 } |
136 CODEGEN_TEST_RUN(StackmapCodegen, Smi::New(1)) | 137 CODEGEN_TEST_RUN(StackmapCodegen, Smi::New(1)) |
137 | 138 |
138 | 139 |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
185 Function::Handle(cls.LookupStaticFunction(function_moo_name)); | 186 Function::Handle(cls.LookupStaticFunction(function_moo_name)); |
186 EXPECT(CompilerTest::TestCompileFunction(function_moo)); | 187 EXPECT(CompilerTest::TestCompileFunction(function_moo)); |
187 EXPECT(function_moo.HasCode()); | 188 EXPECT(function_moo.HasCode()); |
188 | 189 |
189 String& function_foo_name = String::Handle(String::New("foo")); | 190 String& function_foo_name = String::Handle(String::New("foo")); |
190 Function& function_foo = | 191 Function& function_foo = |
191 Function::Handle(cls.LookupStaticFunction(function_foo_name)); | 192 Function::Handle(cls.LookupStaticFunction(function_foo_name)); |
192 EXPECT(CompilerTest::TestCompileFunction(function_foo)); | 193 EXPECT(CompilerTest::TestCompileFunction(function_foo)); |
193 EXPECT(function_foo.HasCode()); | 194 EXPECT(function_foo.HasCode()); |
194 | 195 |
195 // Build and setup a stackmap for function 'A.foo' in order to test the | 196 // Build and setup a stackmap for the call to 'func' in 'A.foo' in order |
196 // traversal of stack maps when a GC happens. | 197 // to test the traversal of stack maps when a GC happens. |
197 StackmapBuilder* builder = new StackmapBuilder(); | 198 StackmapBuilder* builder = new StackmapBuilder(); |
198 EXPECT(builder != NULL); | 199 EXPECT(builder != NULL); |
199 builder->SetSlotAsValue(0); // var i. | 200 builder->SetSlotAsValue(0); // var i. |
200 builder->SetSlotAsObject(1); // var s1. | 201 builder->SetSlotAsObject(1); // var s1. |
201 builder->SetSlotAsValue(2); // var k. | 202 builder->SetSlotAsValue(2); // var k. |
202 builder->SetSlotAsObject(3); // var s2. | 203 builder->SetSlotAsObject(3); // var s2. |
203 builder->SetSlotAsObject(4); // var s3. | 204 builder->SetSlotAsObject(4); // var s3. |
| 205 builder->SetSlotAsObject(5); // First argument to func(i, k). |
| 206 builder->SetSlotAsObject(6); // Second argument to func(i, k). |
204 const Code& code = Code::Handle(function_foo.unoptimized_code()); | 207 const Code& code = Code::Handle(function_foo.unoptimized_code()); |
205 // Search for the pc of the call to 'func'. | 208 // Search for the pc of the call to 'func'. |
206 const PcDescriptors& descriptors = | 209 const PcDescriptors& descriptors = |
207 PcDescriptors::Handle(code.pc_descriptors()); | 210 PcDescriptors::Handle(code.pc_descriptors()); |
| 211 int call_count = 0; |
208 for (int i = 0; i < descriptors.Length(); ++i) { | 212 for (int i = 0; i < descriptors.Length(); ++i) { |
209 if (descriptors.DescriptorKind(i) == PcDescriptors::kFuncCall) { | 213 if (descriptors.DescriptorKind(i) == PcDescriptors::kFuncCall) { |
210 builder->AddEntry(descriptors.PC(i) - code.EntryPoint()); | 214 builder->AddEntry(descriptors.PC(i) - code.EntryPoint()); |
| 215 ++call_count; |
211 } | 216 } |
212 } | 217 } |
| 218 // We can't easily check that we put the stackmap at the correct pc, but |
| 219 // we did if there was exactly one call seen. |
| 220 EXPECT(call_count == 1); |
213 const Array& stack_maps = Array::Handle(builder->FinalizeStackmaps(code)); | 221 const Array& stack_maps = Array::Handle(builder->FinalizeStackmaps(code)); |
214 code.set_stackmaps(stack_maps); | 222 code.set_stackmaps(stack_maps); |
215 | 223 |
216 // Now invoke 'A.moo' and it will trigger a GC when the native function | 224 // Now invoke 'A.moo' and it will trigger a GC when the native function |
217 // is called, this should then cause the stack map of function 'A.foo' | 225 // is called, this should then cause the stack map of function 'A.foo' |
218 // to be traversed and the appropriate objects visited. | 226 // to be traversed and the appropriate objects visited. |
219 GrowableArray<const Object*> arguments; | 227 GrowableArray<const Object*> arguments; |
220 const Array& kNoArgumentNames = Array::Handle(); | 228 const Array& kNoArgumentNames = Array::Handle(); |
221 Object& result = Object::Handle(); | 229 Object& result = Object::Handle(); |
222 result = DartEntry::InvokeStatic(function_foo, arguments, kNoArgumentNames); | 230 result = DartEntry::InvokeStatic(function_foo, arguments, kNoArgumentNames); |
223 EXPECT(!result.IsError()); | 231 EXPECT(!result.IsError()); |
224 } | 232 } |
225 | 233 |
226 } // namespace dart | 234 } // namespace dart |
227 | 235 |
228 #endif // defined TARGET_ARCH_IA32 || defined(TARGET_ARCH_X64) | 236 #endif // defined TARGET_ARCH_IA32 || defined(TARGET_ARCH_X64) |
OLD | NEW |