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/allocation.h" |
6 | #include "platform/assert.h" |
7 | #include "vm/longjump.h" |
8 | #include "vm/unit_test.h" |
9 | |
10 | namespace dart { |
11 | |
12 | class TestValueObject : public ValueObject { |
13 | public: |
14 | explicit TestValueObject(int* ptr) : ptr_(ptr) { |
15 | EXPECT_EQ(1, *ptr_); |
16 | *ptr_ = 2; |
17 | } |
18 | |
19 | virtual ~TestValueObject() { |
20 | EXPECT_EQ(3, *ptr_); |
21 | *ptr_ = 4; |
22 | } |
23 | |
24 | int value() const { return *ptr_; } |
25 | virtual int GetId() const { return 3; } |
26 | |
27 | private: |
28 | int* ptr_; |
29 | }; |
30 | |
31 | class TestStackResource : public StackResource { |
32 | public: |
33 | explicit TestStackResource(int* ptr) |
34 | : StackResource(Thread::Current()), ptr_(ptr) { |
35 | EXPECT_EQ(1, *ptr_); |
36 | *ptr_ = 2; |
37 | } |
38 | |
39 | ~TestStackResource() { |
40 | EXPECT_EQ(6, *ptr_); |
41 | *ptr_ = 7; |
42 | } |
43 | |
44 | int value() const { return *ptr_; } |
45 | virtual int GetId() const { return 3; } |
46 | |
47 | private: |
48 | int* ptr_; |
49 | }; |
50 | |
51 | class TestStackedStackResource : public StackResource { |
52 | public: |
53 | explicit TestStackedStackResource(int* ptr) |
54 | : StackResource(Thread::Current()), ptr_(ptr) { |
55 | EXPECT_EQ(3, *ptr_); |
56 | *ptr_ = 4; |
57 | } |
58 | |
59 | ~TestStackedStackResource() { |
60 | EXPECT_EQ(5, *ptr_); |
61 | *ptr_ = 6; |
62 | } |
63 | |
64 | int value() const { return *ptr_; } |
65 | |
66 | private: |
67 | int* ptr_; |
68 | }; |
69 | |
70 | static void StackAllocatedDestructionHelper(int* ptr) { |
71 | TestValueObject stacked(ptr); |
72 | EXPECT_EQ(2, *ptr); |
73 | *ptr = 3; |
74 | } |
75 | |
76 | ISOLATE_UNIT_TEST_CASE(StackAllocatedDestruction) { |
77 | int data = 1; |
78 | StackAllocatedDestructionHelper(&data); |
79 | EXPECT_EQ(4, data); |
80 | } |
81 | |
82 | static void StackAllocatedLongJumpHelper(int* ptr, LongJumpScope* jump) { |
83 | TestValueObject stacked(ptr); |
84 | EXPECT_EQ(2, *ptr); |
85 | *ptr = 3; |
86 | const Error& error = Error::Handle(LanguageError::New( |
87 | String::Handle(String::New("StackAllocatedLongJump" )))); |
88 | jump->Jump(1, error); |
89 | UNREACHABLE(); |
90 | } |
91 | |
92 | ISOLATE_UNIT_TEST_CASE(StackAllocatedLongJump) { |
93 | LongJumpScope jump; |
94 | int data = 1; |
95 | if (setjmp(*jump.Set()) == 0) { |
96 | StackAllocatedLongJumpHelper(&data, &jump); |
97 | UNREACHABLE(); |
98 | } |
99 | EXPECT_EQ(3, data); |
100 | } |
101 | |
102 | static void StackedStackResourceDestructionHelper(int* ptr) { |
103 | TestStackedStackResource stacked(ptr); |
104 | EXPECT_EQ(4, *ptr); |
105 | *ptr = 5; |
106 | } |
107 | |
108 | static void StackResourceDestructionHelper(int* ptr) { |
109 | TestStackResource stacked(ptr); |
110 | EXPECT_EQ(2, *ptr); |
111 | *ptr = 3; |
112 | StackedStackResourceDestructionHelper(ptr); |
113 | EXPECT_EQ(6, *ptr); |
114 | // Do not set data because the LongJump version does not return control here. |
115 | } |
116 | |
117 | ISOLATE_UNIT_TEST_CASE(StackResourceDestruction) { |
118 | int data = 1; |
119 | StackResourceDestructionHelper(&data); |
120 | EXPECT_EQ(7, data); |
121 | } |
122 | |
123 | static void StackedStackResourceLongJumpHelper(int* ptr, LongJumpScope* jump) { |
124 | TestStackedStackResource stacked(ptr); |
125 | EXPECT_EQ(4, *ptr); |
126 | *ptr = 5; |
127 | const Error& error = Error::Handle(LanguageError::New( |
128 | String::Handle(String::New("StackedStackResourceLongJump" )))); |
129 | jump->Jump(1, error); |
130 | UNREACHABLE(); |
131 | } |
132 | |
133 | static void StackResourceLongJumpHelper(int* ptr, LongJumpScope* jump) { |
134 | TestStackResource stacked(ptr); |
135 | EXPECT_EQ(2, *ptr); |
136 | *ptr = 3; |
137 | StackedStackResourceLongJumpHelper(ptr, jump); |
138 | UNREACHABLE(); |
139 | } |
140 | |
141 | ISOLATE_UNIT_TEST_CASE(StackResourceLongJump) { |
142 | LongJumpScope* base = Thread::Current()->long_jump_base(); |
143 | { |
144 | LongJumpScope jump; |
145 | int data = 1; |
146 | if (setjmp(*jump.Set()) == 0) { |
147 | StackResourceLongJumpHelper(&data, &jump); |
148 | UNREACHABLE(); |
149 | } |
150 | EXPECT_EQ(7, data); |
151 | } |
152 | ASSERT(base == Thread::Current()->long_jump_base()); |
153 | } |
154 | |
155 | } // namespace dart |
156 | |