1 | // Copyright (c) 2013, 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/dart_api_impl.h" |
6 | #include "vm/dart_api_state.h" |
7 | #include "vm/object.h" |
8 | #include "vm/symbols.h" |
9 | #include "vm/unit_test.h" |
10 | |
11 | namespace dart { |
12 | |
13 | FieldPtr LookupField(Dart_Handle library, |
14 | const char* class_name, |
15 | const char* field_name) { |
16 | LibraryPtr raw_library = Library::RawCast(Api::UnwrapHandle(library)); |
17 | Library& lib = Library::ZoneHandle(raw_library); |
18 | const String& classname = |
19 | String::Handle(Symbols::New(Thread::Current(), class_name)); |
20 | Class& cls = Class::Handle(lib.LookupClass(classname)); |
21 | EXPECT(!cls.IsNull()); // No ambiguity error expected. |
22 | |
23 | String& fieldname = String::Handle(String::New(field_name)); |
24 | Field& field = |
25 | Field::ZoneHandle(cls.LookupInstanceFieldAllowPrivate(fieldname)); |
26 | EXPECT(!field.IsNull()); |
27 | return field.raw(); |
28 | } |
29 | |
30 | TEST_CASE(GuardFieldSimpleTest) { |
31 | const char* script_chars = |
32 | "class A {\n" |
33 | " var f1 = 3.0;\n" |
34 | " dynamic f2 = 3;\n" |
35 | " var f3 = List<dynamic>.filled(4, null);\n" |
36 | " foo() {\n" |
37 | " f1 = f1 + f1;\n" |
38 | " }\n" |
39 | " bar() {\n" |
40 | " f2 = null;\n" |
41 | " f2 = 3.0;\n" |
42 | " }\n" |
43 | "}\n" |
44 | "\n" |
45 | "runFoo() {\n" |
46 | " var a = A();\n" |
47 | " for (int i = 0; i < 2000; i++) {\n" |
48 | " a.foo();\n" |
49 | " }\n" |
50 | "}\n" |
51 | "\n" |
52 | "runBar() {\n" |
53 | " var a = A();\n" |
54 | " for (int i = 0; i < 2000; i++) {\n" |
55 | " a.bar();\n" |
56 | " }\n" |
57 | "}\n" |
58 | "main() {\n" |
59 | " for (int i = 0; i < 100; i++) {\n" |
60 | " runFoo();\n" |
61 | " runBar();\n" |
62 | " }\n" |
63 | "}\n" ; |
64 | Dart_Handle lib = TestCase::LoadTestScript(script_chars, NULL); |
65 | Dart_Handle result = Dart_Invoke(lib, NewString("main" ), 0, NULL); |
66 | EXPECT_VALID(result); |
67 | TransitionNativeToVM transition(thread); |
68 | Field& f1 = Field::ZoneHandle(LookupField(lib, "A" , "f1" )); |
69 | Field& f2 = Field::ZoneHandle(LookupField(lib, "A" , "f2" )); |
70 | Field& f3 = Field::ZoneHandle(LookupField(lib, "A" , "f3" )); |
71 | const intptr_t no_length = Field::kNoFixedLength; |
72 | EXPECT_EQ(no_length, f1.guarded_list_length()); |
73 | EXPECT_EQ(kDoubleCid, f1.guarded_cid()); |
74 | EXPECT_EQ(false, f1.is_nullable()); |
75 | EXPECT_EQ(no_length, f2.guarded_list_length()); |
76 | EXPECT_EQ(kDynamicCid, f2.guarded_cid()); |
77 | EXPECT_EQ(true, f2.is_nullable()); |
78 | EXPECT_EQ(no_length, f3.guarded_list_length()); |
79 | } |
80 | |
81 | TEST_CASE(GuardFieldFinalListTest) { |
82 | const char* script_chars = |
83 | "class A {\n" |
84 | " var f1 = 3.0;\n" |
85 | " dynamic f2 = 3;\n" |
86 | " final f3 = List<dynamic>.filled(4, null);\n" |
87 | " foo() {\n" |
88 | " f1 = f1 + f1;\n" |
89 | " }\n" |
90 | " bar() {\n" |
91 | " f2 = null;\n" |
92 | " f2 = 3.0;\n" |
93 | " }\n" |
94 | "}\n" |
95 | "\n" |
96 | "runFoo() {\n" |
97 | " var a = A();\n" |
98 | " for (int i = 0; i < 2000; i++) {\n" |
99 | " a.foo();\n" |
100 | " }\n" |
101 | "}\n" |
102 | "\n" |
103 | "runBar() {\n" |
104 | " var a = A();\n" |
105 | " for (int i = 0; i < 2000; i++) {\n" |
106 | " a.bar();\n" |
107 | " }\n" |
108 | "}\n" |
109 | "main() {\n" |
110 | " for (int i = 0; i < 100; i++) {\n" |
111 | " runFoo();\n" |
112 | " runBar();\n" |
113 | " }\n" |
114 | "}\n" ; |
115 | Dart_Handle lib = TestCase::LoadTestScript(script_chars, NULL); |
116 | Dart_Handle result = Dart_Invoke(lib, NewString("main" ), 0, NULL); |
117 | EXPECT_VALID(result); |
118 | TransitionNativeToVM transition(thread); |
119 | Field& f1 = Field::ZoneHandle(LookupField(lib, "A" , "f1" )); |
120 | Field& f2 = Field::ZoneHandle(LookupField(lib, "A" , "f2" )); |
121 | Field& f3 = Field::ZoneHandle(LookupField(lib, "A" , "f3" )); |
122 | const intptr_t no_length = Field::kNoFixedLength; |
123 | EXPECT_EQ(no_length, f1.guarded_list_length()); |
124 | EXPECT_EQ(kDoubleCid, f1.guarded_cid()); |
125 | EXPECT_EQ(false, f1.is_nullable()); |
126 | EXPECT_EQ(no_length, f2.guarded_list_length()); |
127 | EXPECT_EQ(kDynamicCid, f2.guarded_cid()); |
128 | EXPECT_EQ(true, f2.is_nullable()); |
129 | EXPECT_EQ(4, f3.guarded_list_length()); |
130 | EXPECT_EQ(kArrayCid, f3.guarded_cid()); |
131 | EXPECT_EQ(false, f3.is_nullable()); |
132 | } |
133 | |
134 | TEST_CASE(GuardFieldFinalVariableLengthListTest) { |
135 | const char* script_chars = |
136 | "class A {\n" |
137 | " var f1 = 3.0;\n" |
138 | " dynamic f2 = 3;\n" |
139 | " final f3 = List.empty(growable: true);\n" |
140 | " foo() {\n" |
141 | " f1 = f1 + f1;\n" |
142 | " }\n" |
143 | " bar() {\n" |
144 | " f2 = null;\n" |
145 | " f2 = 3.0;\n" |
146 | " }\n" |
147 | "}\n" |
148 | "\n" |
149 | "runFoo() {\n" |
150 | " var a = A();\n" |
151 | " for (int i = 0; i < 2000; i++) {\n" |
152 | " a.foo();\n" |
153 | " }\n" |
154 | "}\n" |
155 | "\n" |
156 | "runBar() {\n" |
157 | " var a = A();\n" |
158 | " for (int i = 0; i < 2000; i++) {\n" |
159 | " a.bar();\n" |
160 | " }\n" |
161 | "}\n" |
162 | "main() {\n" |
163 | " for (int i = 0; i < 100; i++) {\n" |
164 | " runFoo();\n" |
165 | " runBar();\n" |
166 | " }\n" |
167 | "}\n" ; |
168 | Dart_Handle lib = TestCase::LoadTestScript(script_chars, NULL); |
169 | Dart_Handle result = Dart_Invoke(lib, NewString("main" ), 0, NULL); |
170 | EXPECT_VALID(result); |
171 | TransitionNativeToVM transition(thread); |
172 | Field& f1 = Field::ZoneHandle(LookupField(lib, "A" , "f1" )); |
173 | Field& f2 = Field::ZoneHandle(LookupField(lib, "A" , "f2" )); |
174 | Field& f3 = Field::ZoneHandle(LookupField(lib, "A" , "f3" )); |
175 | const intptr_t no_length = Field::kNoFixedLength; |
176 | EXPECT_EQ(no_length, f1.guarded_list_length()); |
177 | EXPECT_EQ(kDoubleCid, f1.guarded_cid()); |
178 | EXPECT_EQ(false, f1.is_nullable()); |
179 | EXPECT_EQ(no_length, f2.guarded_list_length()); |
180 | EXPECT_EQ(kDynamicCid, f2.guarded_cid()); |
181 | EXPECT_EQ(true, f2.is_nullable()); |
182 | EXPECT_EQ(no_length, f3.guarded_list_length()); |
183 | EXPECT_EQ(kGrowableObjectArrayCid, f3.guarded_cid()); |
184 | EXPECT_EQ(false, f3.is_nullable()); |
185 | } |
186 | |
187 | TEST_CASE(GuardFieldConstructorTest) { |
188 | const char* script_chars = |
189 | "import 'dart:typed_data';\n" |
190 | "class A {\n" |
191 | " var f1 = 3.0;\n" |
192 | " dynamic f2 = 3;\n" |
193 | " final f3;\n" |
194 | " A(x) : f3 = x;\n" |
195 | " foo() {\n" |
196 | " f1 = f1 + f1;\n" |
197 | " }\n" |
198 | " bar() {\n" |
199 | " f2 = null;\n" |
200 | " f2 = 3.0;\n" |
201 | " }\n" |
202 | "}\n" |
203 | "\n" |
204 | "runFoo() {\n" |
205 | " var l = new Float32List(5);\n" |
206 | " for (int i = 0; i < 2000; i++) {\n" |
207 | " var a = new A(l);\n" |
208 | " a.foo();\n" |
209 | " }\n" |
210 | "}\n" |
211 | "\n" |
212 | "runBar() {\n" |
213 | " var l = new Float32List(5);\n" |
214 | " var a = new A(l);\n" |
215 | " for (int i = 0; i < 2000; i++) {\n" |
216 | " a.bar();\n" |
217 | " }\n" |
218 | "}\n" |
219 | "main() {\n" |
220 | " for (int i = 0; i < 100; i++) {\n" |
221 | " runFoo();\n" |
222 | " runBar();\n" |
223 | " }\n" |
224 | "}\n" ; |
225 | Dart_Handle lib = TestCase::LoadTestScript(script_chars, NULL); |
226 | Dart_Handle result = Dart_Invoke(lib, NewString("main" ), 0, NULL); |
227 | EXPECT_VALID(result); |
228 | TransitionNativeToVM transition(thread); |
229 | Field& f1 = Field::ZoneHandle(LookupField(lib, "A" , "f1" )); |
230 | Field& f2 = Field::ZoneHandle(LookupField(lib, "A" , "f2" )); |
231 | Field& f3 = Field::ZoneHandle(LookupField(lib, "A" , "f3" )); |
232 | const intptr_t no_length = Field::kNoFixedLength; |
233 | EXPECT_EQ(no_length, f1.guarded_list_length()); |
234 | EXPECT_EQ(kDoubleCid, f1.guarded_cid()); |
235 | EXPECT_EQ(false, f1.is_nullable()); |
236 | EXPECT_EQ(no_length, f2.guarded_list_length()); |
237 | EXPECT_EQ(kDynamicCid, f2.guarded_cid()); |
238 | EXPECT_EQ(true, f2.is_nullable()); |
239 | const intptr_t length = 5; |
240 | EXPECT_EQ(length, f3.guarded_list_length()); |
241 | EXPECT_EQ(kTypedDataFloat32ArrayCid, f3.guarded_cid()); |
242 | EXPECT_EQ(false, f3.is_nullable()); |
243 | } |
244 | |
245 | TEST_CASE(GuardFieldConstructor2Test) { |
246 | const char* script_chars = |
247 | "import 'dart:typed_data';\n" |
248 | "class A {\n" |
249 | " final f3;\n" |
250 | " A(x) : f3 = x;\n" |
251 | " foo() {\n" |
252 | " }\n" |
253 | " bar() {\n" |
254 | " }\n" |
255 | "}\n" |
256 | "\n" |
257 | "runFoo() {\n" |
258 | " var l = new Float32List(5);\n" |
259 | " for (int i = 0; i < 2000; i++) {\n" |
260 | " var a = new A(l);\n" |
261 | " }\n" |
262 | "}\n" |
263 | "\n" |
264 | "runBar() {\n" |
265 | " var l = new Float32List(99);\n" |
266 | " var a = new A(l);\n" |
267 | "}\n" |
268 | "main() {\n" |
269 | " for (int i = 0; i < 100; i++) {\n" |
270 | " runFoo();\n" |
271 | " runBar();\n" |
272 | " }\n" |
273 | "}\n" ; |
274 | Dart_Handle lib = TestCase::LoadTestScript(script_chars, NULL); |
275 | Dart_Handle result = Dart_Invoke(lib, NewString("main" ), 0, NULL); |
276 | EXPECT_VALID(result); |
277 | TransitionNativeToVM transition(thread); |
278 | Field& f3 = Field::ZoneHandle(LookupField(lib, "A" , "f3" )); |
279 | const intptr_t no_length = Field::kNoFixedLength; |
280 | EXPECT_EQ(no_length, f3.guarded_list_length()); |
281 | EXPECT_EQ(kTypedDataFloat32ArrayCid, f3.guarded_cid()); |
282 | EXPECT_EQ(false, f3.is_nullable()); |
283 | } |
284 | |
285 | } // namespace dart |
286 | |