Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
stack_frame_test.cc
Go to the documentation of this 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
3// BSD-style license that can be found in the LICENSE file.
4
5#include "vm/stack_frame.h"
6#include "include/dart_api.h"
7#include "platform/assert.h"
10#include "vm/dart_api_impl.h"
11#include "vm/dart_entry.h"
12#include "vm/heap/verifier.h"
13#include "vm/resolver.h"
14#include "vm/unit_test.h"
15#include "vm/zone.h"
16
17namespace dart {
18
19// Unit test for empty stack frame iteration.
20ISOLATE_UNIT_TEST_CASE(EmptyStackFrameIteration) {
24 EXPECT(!iterator.HasNextFrame());
25 EXPECT(iterator.NextFrame() == nullptr);
26 VerifyPointersVisitor::VerifyPointers("EmptyStackFrameIterationTest");
27}
28
29// Unit test for empty dart stack frame iteration.
30ISOLATE_UNIT_TEST_CASE(EmptyDartStackFrameIteration) {
33 EXPECT(iterator.NextFrame() == nullptr);
34 VerifyPointersVisitor::VerifyPointers("EmptyDartStackFrameIterationTest");
35}
36
37#define FUNCTION_NAME(name) StackFrame_##name
38#define REGISTER_FUNCTION(name, count) {"" #name, FUNCTION_NAME(name), count},
39
41 NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
42 TransitionNativeToVM transition(arguments->thread());
43 Zone* zone = arguments->thread()->zone();
44 const Instance& expected =
45 Instance::CheckedHandle(zone, arguments->NativeArgAt(0));
46 const Instance& actual =
47 Instance::CheckedHandle(zone, arguments->NativeArgAt(1));
48 if (!expected.OperatorEquals(actual)) {
49 OS::PrintErr("expected: '%s' actual: '%s'\n", expected.ToCString(),
50 actual.ToCString());
51 EXPECT(false);
52 }
53}
54
56 NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
57 TransitionNativeToVM transition(arguments->thread());
58 int count = 0;
60 arguments->thread(),
62 while (frames.NextFrame() != nullptr) {
63 count += 1; // Count the frame.
64 }
65 VerifyPointersVisitor::VerifyPointers("StackFrame_frameCount_Test");
67}
68
71 int count = 0;
74 while (frames.NextFrame() != nullptr) {
75 count += 1; // Count the dart frame.
76 }
77 VerifyPointersVisitor::VerifyPointers("StackFrame_dartFrameCount_Test");
78 NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
80}
81
83 Thread* thread = Thread::Current();
84 Zone* zone = thread->zone();
85
88
89 TransitionNativeToVM transition(thread);
90 const Smi& frame_index_smi =
91 Smi::CheckedHandle(zone, Api::UnwrapHandle(index));
92 const char* expected_name =
93 String::CheckedHandle(zone, Api::UnwrapHandle(name)).ToCString();
94 int frame_index = frame_index_smi.Value();
95 int count = 0;
97 StackFrame* frame = frames.NextFrame();
98 while (frame != nullptr) {
99 if (count == frame_index) {
100 // Find the function corresponding to this frame and check if it
101 // matches the function name passed in.
102 const Function& function =
103 Function::Handle(zone, frame->LookupDartFunction());
104 if (function.IsNull()) {
105 FATAL("StackFrame_validateFrame fails, invalid dart frame.\n");
106 }
107 const char* name = function.ToFullyQualifiedCString();
108 // Currently all unit tests are loaded as being part of dart:core-lib.
110 const Library& lib =
111 Library::Handle(zone, Library::LookupLibrary(thread, url));
112 ASSERT(!lib.IsNull());
113 const char* lib_name = String::Handle(zone, lib.url()).ToCString();
114 char* full_name = OS::SCreate(zone, "%s_%s", lib_name, expected_name);
115 EXPECT_STREQ(full_name, name);
116 return;
117 }
118 count += 1; // Count the dart frames.
119 frame = frames.NextFrame();
120 }
121 FATAL("StackFrame_validateFrame fails, frame count < index passed in.\n");
122}
123
124// List all native functions implemented in the vm or core boot strap dart
125// libraries so that we can resolve the native function to it's entry
126// point.
127#define STACKFRAME_NATIVE_LIST(V) \
128 V(StackFrame_equals, 2) \
129 V(StackFrame_frameCount, 0) \
130 V(StackFrame_dartFrameCount, 0) \
131 V(StackFrame_validateFrame, 2)
132
133static struct NativeEntries {
134 const char* name_;
136 int argument_count_;
138
140 int argument_count,
141 bool* auto_setup_scope) {
142 ASSERT(auto_setup_scope != nullptr);
143 *auto_setup_scope = false;
146 ASSERT(obj.IsString());
147 const char* function_name = obj.ToCString();
148 ASSERT(function_name != nullptr);
149 int num_entries = sizeof(BuiltinEntries) / sizeof(struct NativeEntries);
150 for (int i = 0; i < num_entries; i++) {
151 struct NativeEntries* entry = &(BuiltinEntries[i]);
152 if ((strcmp(function_name, entry->name_) == 0) &&
153 (entry->argument_count_ == argument_count)) {
154 return reinterpret_cast<Dart_NativeFunction>(entry->function_);
155 }
156 }
157 return nullptr;
158}
159
160// Unit test case to verify stack frame iteration.
161TEST_CASE(ValidateStackFrameIteration) {
162 const char* nullable_tag = TestCase::NullableTag();
163 // clang-format off
164 auto kScriptChars = Utils::CStringUniquePtr(
166 nullptr,
167 "class StackFrame {"
168 " @pragma('vm:external-name', 'StackFrame_equals')\n"
169 " external static equals(var obj1, var obj2);\n"
170 " @pragma('vm:external-name', 'StackFrame_frameCount')\n"
171 " external static int frameCount();\n"
172 " @pragma('vm:external-name', 'StackFrame_dartFrameCount')\n"
173 " external static int dartFrameCount();\n"
174 " @pragma('vm:external-name', 'StackFrame_validateFrame')\n"
175 " external static validateFrame(int index, String name);"
176 "} "
177 "class First {"
178 " First() { }"
179 " int%s method1(int%s param) {"
180 " if (param == 1) {"
181 " param = method2(200);"
182 " } else {"
183 " param = method2(100);"
184 " }"
185 " }"
186 " int%s method2(int param) {"
187 " if (param == 200) {"
188 " First.staticmethod(this, param);"
189 " } else {"
190 " First.staticmethod(this, 10);"
191 " }"
192 " }"
193 " static int%s staticmethod(First obj, int param) {"
194 " if (param == 10) {"
195 " obj.method3(10);"
196 " } else {"
197 " obj.method3(200);"
198 " }"
199 " }"
200 " method3(int param) {"
201 " StackFrame.equals(9, StackFrame.frameCount());"
202 " StackFrame.equals(7, StackFrame.dartFrameCount());"
203 " StackFrame.validateFrame(0, \"StackFrame_validateFrame\");"
204 " StackFrame.validateFrame(1, \"First_method3\");"
205 " StackFrame.validateFrame(2, \"First_staticmethod\");"
206 " StackFrame.validateFrame(3, \"First_method2\");"
207 " StackFrame.validateFrame(4, \"First_method1\");"
208 " StackFrame.validateFrame(5, \"Second_method1\");"
209 " StackFrame.validateFrame(6, \"StackFrameTest_testMain\");"
210 " }"
211 "}"
212 "class Second {"
213 " Second() { }"
214 " int%s method1(int%s param) {"
215 " if (param == 1) {"
216 " param = method2(200);"
217 " } else {"
218 " First obj = new First();"
219 " param = obj.method1(1);"
220 " param = obj.method1(2);"
221 " }"
222 " }"
223 " int%s method2(int param) {"
224 " Second.staticmethod(this, param);"
225 " }"
226 " static int%s staticmethod(Second obj, int param) {"
227 " obj.method3(10);"
228 " }"
229 " method3(int param) {"
230 " StackFrame.equals(8, StackFrame.frameCount());"
231 " StackFrame.equals(6, StackFrame.dartFrameCount());"
232 " StackFrame.validateFrame(0, \"StackFrame_validateFrame\");"
233 " StackFrame.validateFrame(1, \"Second_method3\");"
234 " StackFrame.validateFrame(2, \"Second_staticmethod\");"
235 " StackFrame.validateFrame(3, \"Second_method2\");"
236 " StackFrame.validateFrame(4, \"Second_method1\");"
237 " StackFrame.validateFrame(5, \"StackFrameTest_testMain\");"
238 " }"
239 "}"
240 "class StackFrameTest {"
241 " static testMain() {"
242 " Second obj = new Second();"
243 " obj.method1(1);"
244 " obj.method1(2);"
245 " }"
246 "}",
247 nullable_tag, nullable_tag, nullable_tag, nullable_tag, nullable_tag,
248 nullable_tag, nullable_tag, nullable_tag),
249 std::free);
250 // clang-format on
252 kScriptChars.get(),
253 reinterpret_cast<Dart_NativeEntryResolver>(native_lookup));
254 Dart_Handle cls = Dart_GetClass(lib, NewString("StackFrameTest"));
255 EXPECT_VALID(Dart_Invoke(cls, NewString("testMain"), 0, nullptr));
256}
257
258// Unit test case to verify stack frame iteration.
259TEST_CASE(ValidateNoSuchMethodStackFrameIteration) {
260 const char* kScriptChars;
261 // The true stack depends on which strategy we are using for noSuchMethod. The
262 // stacktrace as seen by Dart is the same either way because dispatcher
263 // methods are marked invisible.
264 if (FLAG_lazy_dispatchers) {
265 kScriptChars =
266 "class StackFrame {"
267 " @pragma('vm:external-name', 'StackFrame_equals')\n"
268 " external static equals(var obj1, var obj2);\n"
269 " @pragma('vm:external-name', 'StackFrame_frameCount')\n"
270 " external static int frameCount();\n"
271 " @pragma('vm:external-name', 'StackFrame_dartFrameCount')\n"
272 " external static int dartFrameCount();\n"
273 " @pragma('vm:external-name', 'StackFrame_validateFrame')\n"
274 " external static validateFrame(int index, String name);"
275 "} "
276 "class StackFrame2Test {"
277 " StackFrame2Test() {}"
278 " noSuchMethod(Invocation im) {"
279 " /* We should have 6 general frames and 4 dart frames as follows:"
280 " * exit frame"
281 " * dart frame corresponding to StackFrame.frameCount"
282 " * dart frame corresponding to StackFrame2Test.noSuchMethod"
283 " * frame for instance function invocation stub calling "
284 "noSuchMethod"
285 " * dart frame corresponding to StackFrame2Test.testMain"
286 " * entry frame"
287 " */"
288 " StackFrame.equals(6, StackFrame.frameCount());"
289 " StackFrame.equals(4, StackFrame.dartFrameCount());"
290 " StackFrame.validateFrame(0, \"StackFrame_validateFrame\");"
291 " StackFrame.validateFrame(1, \"StackFrame2Test_noSuchMethod\");"
292 " StackFrame.validateFrame(2, \"StackFrame2Test_foo\");"
293 " StackFrame.validateFrame(3, \"StackFrame2Test_testMain\");"
294 " return 5;"
295 " }"
296 " static testMain() {"
297 " /* Declare |obj| dynamic so that noSuchMethod can be"
298 " * called in strong mode. */"
299 " dynamic obj = new StackFrame2Test();"
300 " StackFrame.equals(5, obj.foo(101, 202));"
301 " }"
302 "}";
303 } else {
304 kScriptChars =
305 "class StackFrame {"
306 " @pragma('vm:external-name', 'StackFrame_equals')\n"
307 " external static equals(var obj1, var obj2);\n"
308 " @pragma('vm:external-name', 'StackFrame_frameCount')\n"
309 " external static int frameCount();\n"
310 " @pragma('vm:external-name', 'StackFrame_dartFrameCount')\n"
311 " external static int dartFrameCount();\n"
312 " @pragma('vm:external-name', 'StackFrame_validateFrame')\n"
313 " external static validateFrame(int index, String name);"
314 "} "
315 "class StackFrame2Test {"
316 " StackFrame2Test() {}"
317 " noSuchMethod(Invocation im) {"
318 " /* We should have 8 general frames and 3 dart frames as follows:"
319 " * exit frame"
320 " * dart frame corresponding to StackFrame.frameCount"
321 " * dart frame corresponding to StackFrame2Test.noSuchMethod"
322 " * entry frame"
323 " * exit frame (call to runtime NoSuchMethodFromCallStub)"
324 " * IC stub"
325 " * dart frame corresponding to StackFrame2Test.testMain"
326 " * entry frame"
327 " */"
328 " StackFrame.equals(8, StackFrame.frameCount());"
329 " StackFrame.equals(3, StackFrame.dartFrameCount());"
330 " StackFrame.validateFrame(0, \"StackFrame_validateFrame\");"
331 " StackFrame.validateFrame(1, \"StackFrame2Test_noSuchMethod\");"
332 " StackFrame.validateFrame(2, \"StackFrame2Test_testMain\");"
333 " return 5;"
334 " }"
335 " static testMain() {"
336 " /* Declare |obj| dynamic so that noSuchMethod can be"
337 " * called in strong mode. */"
338 " dynamic obj = new StackFrame2Test();"
339 " StackFrame.equals(5, obj.foo(101, 202));"
340 " }"
341 "}";
342 }
344 kScriptChars, reinterpret_cast<Dart_NativeEntryResolver>(native_lookup));
345 Dart_Handle cls = Dart_GetClass(lib, NewString("StackFrame2Test"));
346 EXPECT_VALID(Dart_Invoke(cls, NewString("testMain"), 0, nullptr));
347}
348
349} // namespace dart
int count
#define EXPECT(type, expectedAlignment, expectedSize)
#define FUNCTION_NAME(name)
Definition builtin.h:19
static ObjectPtr UnwrapHandle(Dart_Handle object)
StackFrame * NextFrame()
virtual bool OperatorEquals(const Instance &other) const
Definition object.cc:20896
static LibraryPtr LookupLibrary(Thread *thread, const String &url)
Definition object.cc:14646
StringPtr url() const
Definition object.h:5068
Thread * thread() const
void SetReturn(const Object &value) const
ObjectPtr NativeArgAt(int index) const
static void static void PrintErr(const char *format,...) PRINTF_ATTRIBUTE(1
static char * SCreate(Zone *zone, const char *format,...) PRINTF_ATTRIBUTE(2
virtual const char * ToCString() const
Definition object.h:366
bool IsNull() const
Definition object.h:363
static Object & Handle()
Definition object.h:407
static SmiPtr New(intptr_t value)
Definition object.h:9985
intptr_t Value() const
Definition object.h:9969
static StringPtr New(const char *cstr, Heap::Space space=Heap::kNew)
Definition object.cc:23777
static Dart_Handle LoadTestScript(const char *script, Dart_NativeEntryResolver resolver, const char *lib_uri=RESOLVED_USER_TEST_URI, bool finalize=true, bool allow_compile_errors=false)
Definition unit_test.cc:422
static const char * url()
Definition unit_test.cc:184
static const char * NullableTag()
Definition unit_test.h:421
Zone * zone() const
static Thread * Current()
Definition thread.h:361
std::unique_ptr< char, decltype(std::free) * > CStringUniquePtr
Definition utils.h:644
static void VerifyPointers(const char *msg, MarkExpectation mark_expectation=kForbidMarked)
Definition verifier.cc:81
struct _Dart_Handle * Dart_Handle
Definition dart_api.h:258
Dart_NativeFunction(* Dart_NativeEntryResolver)(Dart_Handle name, int num_of_arguments, bool *auto_setup_scope)
Definition dart_api.h:3225
struct _Dart_NativeArguments * Dart_NativeArguments
Definition dart_api.h:3010
void(* Dart_NativeFunction)(Dart_NativeArguments arguments)
Definition dart_api.h:3198
#define ASSERT(E)
double frame
Definition examples.cpp:31
#define FATAL(error)
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
Dart_NativeFunction function
Definition fuchsia.cc:51
#define REGISTER_FUNCTION(name, count)
Definition fuchsia.cc:41
int argument_count
Definition fuchsia.cc:52
const char *const name
void FUNCTION_NAME() StackFrame_dartFrameCount(Dart_NativeArguments args)
DART_EXPORT Dart_Handle Dart_Invoke(Dart_Handle target, Dart_Handle name, int number_of_arguments, Dart_Handle *arguments)
DART_EXPORT Dart_Handle Dart_GetClass(Dart_Handle library, Dart_Handle class_name)
void FUNCTION_NAME() StackFrame_validateFrame(Dart_NativeArguments args)
static Dart_NativeFunction native_lookup(Dart_Handle name, int argument_count, bool *auto_setup_scope)
static struct dart::NativeEntries BuiltinEntries[]
DART_EXPORT Dart_Handle Dart_GetNativeArgument(Dart_NativeArguments args, int index)
Dart_Handle NewString(const char *str)
void FUNCTION_NAME() StackFrame_equals(Dart_NativeArguments args)
void FUNCTION_NAME() StackFrame_frameCount(Dart_NativeArguments args)
const char *const function_name
#define STACKFRAME_NATIVE_LIST(V)
const char *const name_
#define ISOLATE_UNIT_TEST_CASE(name)
Definition unit_test.h:64
#define TEST_CASE(name)
Definition unit_test.h:85
#define EXPECT_VALID(handle)
Definition unit_test.h:650