Flutter Engine
The Flutter Engine
object_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 <limits>
6#include <memory>
7
8#include "include/dart_api.h"
9
10#include "bin/builtin.h"
11#include "bin/vmservice_impl.h"
12
13#include "platform/globals.h"
14
15#include "vm/class_finalizer.h"
17#include "vm/code_descriptors.h"
22#include "vm/dart_api_impl.h"
23#include "vm/dart_entry.h"
24#include "vm/debugger.h"
26#include "vm/flags.h"
27#include "vm/isolate.h"
28#include "vm/message_handler.h"
29#include "vm/object.h"
30#include "vm/object_store.h"
31#include "vm/resolver.h"
32#include "vm/simulator.h"
33#include "vm/symbols.h"
34#include "vm/tagged_pointer.h"
35#include "vm/unit_test.h"
36#include "vm/zone_text_buffer.h"
37
38namespace dart {
39
40#define Z (thread->zone())
41
42DECLARE_FLAG(bool, write_protect_code);
43
44static ClassPtr CreateDummyClass(const String& class_name,
45 const Script& script) {
46 const Class& cls = Class::Handle(Class::New(
47 Library::Handle(), class_name, script, TokenPosition::kNoSource));
48 cls.set_is_synthesized_class_unsafe(); // Dummy class for testing.
50 return cls.ptr();
51}
52
54 // Allocate the class first.
55 const String& class_name = String::Handle(Symbols::New(thread, "MyClass"));
56 const Script& script = Script::Handle();
58
59 // Class has no fields and no functions yet.
60 EXPECT_EQ(Array::Handle(cls.fields()).Length(), 0);
61 EXPECT_EQ(Array::Handle(cls.current_functions()).Length(), 0);
62
63 // Setup the interfaces in the class.
64 // Normally the class finalizer is resolving super types and interfaces
65 // before finalizing the types in a class. A side-effect of this is setting
66 // the is_implemented() bit on a class. We do that manually here.
67 const Array& interfaces = Array::Handle(Array::New(2));
68 Class& interface = Class::Handle();
69 String& interface_name = String::Handle();
70 interface_name = Symbols::New(thread, "Harley");
71 interface = CreateDummyClass(interface_name, script);
72 interfaces.SetAt(0, Type::Handle(Type::NewNonParameterizedType(interface)));
73 interface.set_is_implemented_unsafe();
74 interface_name = Symbols::New(thread, "Norton");
75 interface = CreateDummyClass(interface_name, script);
76 interfaces.SetAt(1, Type::Handle(Type::NewNonParameterizedType(interface)));
77 interface.set_is_implemented_unsafe();
78 cls.set_interfaces(interfaces);
79
80 // Finalization of types happens before the fields and functions have been
81 // parsed.
83
84 // Create and populate the function arrays.
85 const Array& functions = Array::Handle(Array::New(6));
89 function_name = Symbols::New(thread, "foo");
90 signature = FunctionType::New();
92 UntaggedFunction::kRegularFunction, false, false,
93 false, false, false, cls, TokenPosition::kMinSource);
94 functions.SetAt(0, function);
95 function_name = Symbols::New(thread, "bar");
96 signature = FunctionType::New();
98 UntaggedFunction::kRegularFunction, false, false,
99 false, false, false, cls, TokenPosition::kMinSource);
100
101 const int kNumFixedParameters = 2;
102 const int kNumOptionalParameters = 3;
103 const bool kAreOptionalPositional = true;
104 signature.set_num_fixed_parameters(kNumFixedParameters);
105 signature.SetNumOptionalParameters(kNumOptionalParameters,
106 kAreOptionalPositional);
107 functions.SetAt(1, function);
108
109 function_name = Symbols::New(thread, "baz");
110 signature = FunctionType::New();
112 UntaggedFunction::kRegularFunction, false, false,
113 false, false, false, cls, TokenPosition::kMinSource);
114 functions.SetAt(2, function);
115
116 function_name = Symbols::New(thread, "Foo");
117 signature = FunctionType::New();
119 UntaggedFunction::kRegularFunction, true, false,
120 false, false, false, cls, TokenPosition::kMinSource);
121
122 functions.SetAt(3, function);
123 function_name = Symbols::New(thread, "Bar");
124 signature = FunctionType::New();
126 UntaggedFunction::kRegularFunction, true, false,
127 false, false, false, cls, TokenPosition::kMinSource);
128 functions.SetAt(4, function);
129 function_name = Symbols::New(thread, "BaZ");
130 signature = FunctionType::New();
132 UntaggedFunction::kRegularFunction, true, false,
133 false, false, false, cls, TokenPosition::kMinSource);
134 functions.SetAt(5, function);
135
136 // Setup the functions in the class.
137 {
138 SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
139 cls.SetFunctions(functions);
140 // The class can now be finalized.
141 cls.Finalize();
142 }
143
144 function_name = String::New("Foo");
146 EXPECT(function.IsNull());
148 EXPECT(!function.IsNull());
150 EXPECT_EQ(cls.ptr(), function.Owner());
151 EXPECT(function.is_static());
152 function_name = String::New("baz");
154 EXPECT(!function.IsNull());
156 EXPECT_EQ(cls.ptr(), function.Owner());
157 EXPECT(!function.is_static());
159 EXPECT(function.IsNull());
160
161 function_name = String::New("foo");
163 EXPECT(!function.IsNull());
164 EXPECT_EQ(0, function.num_fixed_parameters());
165 EXPECT(!function.HasOptionalParameters());
166
167 function_name = String::New("bar");
169 EXPECT(!function.IsNull());
170 EXPECT_EQ(kNumFixedParameters, function.num_fixed_parameters());
171 EXPECT_EQ(kNumOptionalParameters, function.NumOptionalParameters());
172}
173
174ISOLATE_UNIT_TEST_CASE(SixtyThousandDartClasses) {
175 auto zone = thread->zone();
176 auto isolate_group = thread->isolate_group();
177 auto class_table = isolate_group->class_table();
178
179 const intptr_t start_cid = class_table->NumCids();
180 const intptr_t num_classes = std::numeric_limits<uint16_t>::max() - start_cid;
181
182 const Script& script = Script::Handle(zone);
183 String& name = String::Handle(zone);
184 Class& cls = Class::Handle(zone);
185 Field& field = Field::Handle(zone);
186 Array& fields = Array::Handle(zone);
188 Instance& instance2 = Instance::Handle(zone);
189
190 const auto& instances =
192
193 // Create many top-level classes - they should not consume 16-bit range.
194 {
195 SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
196 for (intptr_t i = 0; i < (1 << 16); ++i) {
197 cls = CreateDummyClass(Symbols::TopLevel(), script);
198 cls.Finalize();
200 }
201 }
202
203 // Create many concrete classes - they should occupy the entire 16-bit space.
204 for (intptr_t i = 0; i < num_classes; ++i) {
205 name = Symbols::New(thread, OS::SCreate(zone, "MyClass%" Pd "", i));
207 EXPECT_EQ(start_cid + i, cls.id());
208
209 const intptr_t num_fields = (i % 10);
210 fields = Array::New(num_fields);
211 for (intptr_t f = 0; f < num_fields; ++f) {
212 name =
213 Symbols::New(thread, OS::SCreate(zone, "myField_%" Pd "_%" Pd, i, f));
214 field = Field::New(name, false, false, false, true, false, cls,
215 Object::dynamic_type(), TokenPosition::kMinSource,
217 fields.SetAt(f, field);
218 }
219
220 cls.set_interfaces(Array::empty_array());
221 {
222 SafepointWriteRwLocker ml(thread,
223 thread->isolate_group()->program_lock());
224 cls.SetFunctions(Array::empty_array());
225 cls.SetFields(fields);
226 cls.Finalize();
227 }
228
229 instance = Instance::New(cls);
230 for (intptr_t f = 0; f < num_fields; ++f) {
231 field ^= fields.At(f);
232 name = Symbols::New(thread,
233 OS::SCreate(zone, "myFieldValue_%" Pd "_%" Pd, i, f));
234 instance.SetField(field, name);
235 }
236 instances.Add(instance);
237 }
238 EXPECT_EQ((1 << 16) - 1, class_table->NumCids());
239
240 // Ensure GC runs and can recognize all those new instances.
241 isolate_group->heap()->CollectAllGarbage();
242
243 // Ensure the instances are what we expect.
244 for (intptr_t i = 0; i < num_classes; ++i) {
245 instance ^= instances.At(i);
246 cls = instance.clazz();
247 fields = cls.fields();
248
249 name = cls.Name();
250 EXPECT(strstr(name.ToCString(), OS::SCreate(zone, "MyClass%" Pd "", i)) !=
251 0);
252 EXPECT_EQ((i % 10), fields.Length());
253
254 for (intptr_t f = 0; f < fields.Length(); ++f) {
255 field ^= fields.At(f);
256 instance2 ^= instance.GetField(field);
257 EXPECT(strstr(instance2.ToCString(),
258 OS::SCreate(zone, "myFieldValue_%" Pd "_%" Pd, i, f)) != 0);
259 }
260 }
261}
262
264 const Type& type1 = Type::Handle(Type::Double());
265 const Type& type2 = Type::Handle(Type::StringType());
266 const TypeArguments& type_arguments1 =
268 type_arguments1.SetTypeAt(0, type1);
269 type_arguments1.SetTypeAt(1, type2);
270 const TypeArguments& type_arguments2 =
272 type_arguments2.SetTypeAt(0, type1);
273 type_arguments2.SetTypeAt(1, type2);
274 EXPECT_NE(type_arguments1.ptr(), type_arguments2.ptr());
275 OS::PrintErr("1: %s\n", type_arguments1.ToCString());
276 OS::PrintErr("2: %s\n", type_arguments2.ToCString());
277 EXPECT(type_arguments1.Equals(type_arguments2));
278 TypeArguments& type_arguments3 = TypeArguments::Handle();
279 type_arguments1.Canonicalize(thread);
280 type_arguments3 ^= type_arguments2.Canonicalize(thread);
281 EXPECT_EQ(type_arguments1.ptr(), type_arguments3.ptr());
282}
283
284TEST_CASE(Class_EndTokenPos) {
285 const char* kScript =
286 "\n"
287 "class A {\n"
288 " /**\n"
289 " * Description of foo().\n"
290 " */\n"
291 " foo(a) { return '''\"}'''; }\n"
292 " // }\n"
293 " var bar = '\\'}';\n"
294 "}\n";
295 Dart_Handle lib_h = TestCase::LoadTestScript(kScript, nullptr);
296 EXPECT_VALID(lib_h);
297 TransitionNativeToVM transition(thread);
298 Library& lib = Library::Handle();
299 lib ^= Api::UnwrapHandle(lib_h);
300 EXPECT(!lib.IsNull());
301 const Class& cls =
303 EXPECT(!cls.IsNull());
304 const Error& error = Error::Handle(cls.EnsureIsFinalized(thread));
305 EXPECT(error.IsNull());
306 const TokenPosition end_token_pos = cls.end_token_pos();
307 const Script& scr = Script::Handle(cls.script());
308 intptr_t line;
309 intptr_t col;
310 EXPECT(scr.GetTokenLocation(end_token_pos, &line, &col));
311 EXPECT_EQ(9, line);
312 EXPECT_EQ(1, col);
313}
314
316 // Allocate the class first.
317 String& class_name = String::Handle(Symbols::New(thread, "EmptyClass"));
319 const Class& empty_class =
321
322 // EmptyClass has no fields and no functions.
323 EXPECT_EQ(Array::Handle(empty_class.fields()).Length(), 0);
324 EXPECT_EQ(Array::Handle(empty_class.current_functions()).Length(), 0);
325
327 {
328 SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
329 empty_class.Finalize();
330 }
331
332 EXPECT_EQ(kObjectAlignment, empty_class.host_instance_size());
334 EXPECT_EQ(empty_class.ptr(), instance.clazz());
335
336 class_name = Symbols::New(thread, "OneFieldClass");
337 const Class& one_field_class =
339
340 // No fields, functions, or super type for the OneFieldClass.
341 EXPECT_EQ(Array::Handle(empty_class.fields()).Length(), 0);
342 EXPECT_EQ(Array::Handle(empty_class.current_functions()).Length(), 0);
343 EXPECT_EQ(empty_class.super_type(), AbstractType::null());
345
346 const Array& one_fields = Array::Handle(Array::New(1));
347 const String& field_name = String::Handle(Symbols::New(thread, "the_field"));
348 const Field& field = Field::Handle(
349 Field::New(field_name, false, false, false, true, false, one_field_class,
350 Object::dynamic_type(), TokenPosition::kMinSource,
352 one_fields.SetAt(0, field);
353 {
354 SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
355 one_field_class.SetFields(one_fields);
356 one_field_class.Finalize();
357 }
358 intptr_t header_size = sizeof(UntaggedObject);
359 EXPECT_EQ(Utils::RoundUp((header_size + (1 * kWordSize)), kObjectAlignment),
360 one_field_class.host_instance_size());
361 EXPECT_EQ(header_size, field.HostOffset());
362 EXPECT(!one_field_class.is_implemented());
363 one_field_class.set_is_implemented_unsafe();
364 EXPECT(one_field_class.is_implemented());
365}
366
368 const Smi& smi = Smi::Handle(Smi::New(5));
369 Object& smi_object = Object::Handle(smi.ptr());
370 EXPECT(smi.IsSmi());
371 EXPECT(smi_object.IsSmi());
372 EXPECT_EQ(5, smi.Value());
373 const Object& object = Object::Handle();
374 EXPECT(!object.IsSmi());
375 smi_object = Object::null();
376 EXPECT(!smi_object.IsSmi());
377
380 EXPECT(smi.Equals(smi));
381 EXPECT(!smi.Equals(Smi::Handle()));
382
384 EXPECT(Smi::IsValid(-15));
385 EXPECT(Smi::IsValid(0xFFu));
386// Upper two bits must be either 00 or 11.
387#if defined(ARCH_IS_64_BIT) && !defined(DART_COMPRESSED_POINTERS)
389 EXPECT(Smi::IsValid(0x3FFFFFFFFFFFFFFF));
390 EXPECT(Smi::IsValid(-1));
391#else
393 EXPECT(Smi::IsValid(0x3FFFFFFF));
394 EXPECT(Smi::IsValid(-1));
395 EXPECT(!Smi::IsValid(0xFFFFFFFFu));
396#endif
397
398 EXPECT_EQ(5, smi.AsInt64Value());
399 EXPECT_EQ(5.0, smi.AsDoubleValue());
400
401 Smi& a = Smi::Handle(Smi::New(5));
402 Smi& b = Smi::Handle(Smi::New(3));
403 EXPECT_EQ(1, a.CompareWith(b));
404 EXPECT_EQ(-1, b.CompareWith(a));
405 EXPECT_EQ(0, a.CompareWith(a));
406
407 Smi& c = Smi::Handle(Smi::New(-1));
408
409 Mint& mint1 = Mint::Handle();
410 mint1 ^= Integer::New(DART_2PART_UINT64_C(0x7FFFFFFF, 100));
411 Mint& mint2 = Mint::Handle();
412 mint2 ^= Integer::New(-DART_2PART_UINT64_C(0x7FFFFFFF, 100));
413 EXPECT_EQ(-1, a.CompareWith(mint1));
414 EXPECT_EQ(1, a.CompareWith(mint2));
415 EXPECT_EQ(-1, c.CompareWith(mint1));
416 EXPECT_EQ(1, c.CompareWith(mint2));
417}
418
419ISOLATE_UNIT_TEST_CASE(StringCompareTo) {
420 const String& abcd = String::Handle(String::New("abcd"));
421 const String& abce = String::Handle(String::New("abce"));
422 EXPECT_EQ(0, abcd.CompareTo(abcd));
423 EXPECT_EQ(0, abce.CompareTo(abce));
424 EXPECT(abcd.CompareTo(abce) < 0);
425 EXPECT(abce.CompareTo(abcd) > 0);
426
427 const int kMonkeyLen = 4;
428 const uint8_t monkey_utf8[kMonkeyLen] = {0xf0, 0x9f, 0x90, 0xb5};
429 const String& monkey_face =
430 String::Handle(String::FromUTF8(monkey_utf8, kMonkeyLen));
431 const int kDogLen = 4;
432 // 0x1f436 DOG FACE.
433 const uint8_t dog_utf8[kDogLen] = {0xf0, 0x9f, 0x90, 0xb6};
434 const String& dog_face = String::Handle(String::FromUTF8(dog_utf8, kDogLen));
435 EXPECT_EQ(0, monkey_face.CompareTo(monkey_face));
436 EXPECT_EQ(0, dog_face.CompareTo(dog_face));
437 EXPECT(monkey_face.CompareTo(dog_face) < 0);
438 EXPECT(dog_face.CompareTo(monkey_face) > 0);
439
440 const int kDominoLen = 4;
441 // 0x1f036 DOMINO TILE HORIZONTAL-00-05.
442 const uint8_t domino_utf8[kDominoLen] = {0xf0, 0x9f, 0x80, 0xb6};
443 const String& domino =
444 String::Handle(String::FromUTF8(domino_utf8, kDominoLen));
445 EXPECT_EQ(0, domino.CompareTo(domino));
446 EXPECT(domino.CompareTo(dog_face) < 0);
447 EXPECT(domino.CompareTo(monkey_face) < 0);
448 EXPECT(dog_face.CompareTo(domino) > 0);
449 EXPECT(monkey_face.CompareTo(domino) > 0);
450
451 EXPECT(abcd.CompareTo(monkey_face) < 0);
452 EXPECT(abce.CompareTo(monkey_face) < 0);
453 EXPECT(abcd.CompareTo(domino) < 0);
454 EXPECT(abce.CompareTo(domino) < 0);
455 EXPECT(domino.CompareTo(abcd) > 0);
456 EXPECT(domino.CompareTo(abcd) > 0);
457 EXPECT(monkey_face.CompareTo(abce) > 0);
458 EXPECT(monkey_face.CompareTo(abce) > 0);
459}
460
461ISOLATE_UNIT_TEST_CASE(StringEncodeIRI) {
462 const char* kInput =
463 "file:///usr/local/johnmccutchan/workspace/dart-repo/dart/test.dart";
464 const char* kOutput =
465 "file%3A%2F%2F%2Fusr%2Flocal%2Fjohnmccutchan%2Fworkspace%2F"
466 "dart-repo%2Fdart%2Ftest.dart";
467 const String& input = String::Handle(String::New(kInput));
468 const char* encoded = String::EncodeIRI(input);
469 EXPECT(strcmp(encoded, kOutput) == 0);
470}
471
472ISOLATE_UNIT_TEST_CASE(StringDecodeIRI) {
473 const char* kOutput =
474 "file:///usr/local/johnmccutchan/workspace/dart-repo/dart/test.dart";
475 const char* kInput =
476 "file%3A%2F%2F%2Fusr%2Flocal%2Fjohnmccutchan%2Fworkspace%2F"
477 "dart-repo%2Fdart%2Ftest.dart";
478 const String& input = String::Handle(String::New(kInput));
480 const String& decoded = String::Handle(String::DecodeIRI(input));
481 EXPECT(output.Equals(decoded));
482}
483
484ISOLATE_UNIT_TEST_CASE(StringDecodeIRIInvalid) {
485 String& input = String::Handle();
486 input = String::New("file%");
487 String& decoded = String::Handle();
488 decoded = String::DecodeIRI(input);
489 EXPECT(decoded.IsNull());
490 input = String::New("file%3");
491 decoded = String::DecodeIRI(input);
492 EXPECT(decoded.IsNull());
493 input = String::New("file%3g");
494 decoded = String::DecodeIRI(input);
495 EXPECT(decoded.IsNull());
496}
497
498ISOLATE_UNIT_TEST_CASE(StringIRITwoByte) {
499 const intptr_t kInputLen = 3;
500 const uint16_t kInput[kInputLen] = {'x', '/', 256};
501 const String& input = String::Handle(String::FromUTF16(kInput, kInputLen));
502 const intptr_t kOutputLen = 10;
503 const uint16_t kOutput[kOutputLen] = {'x', '%', '2', 'F', '%',
504 'C', '4', '%', '8', '0'};
506 const String& encoded = String::Handle(String::New(String::EncodeIRI(input)));
507 EXPECT(output.Equals(encoded));
509 EXPECT(input.Equals(decoded));
510}
511
513// On 64-bit architectures a Smi is stored in a 64 bit word. A Midint cannot
514// be allocated if it does fit into a Smi.
515#if !defined(ARCH_IS_64_BIT) || defined(DART_COMPRESSED_POINTERS)
516 {
517 Mint& med = Mint::Handle();
518 EXPECT(med.IsNull());
519 int64_t v = DART_2PART_UINT64_C(1, 0);
520 med ^= Integer::New(v);
521 EXPECT_EQ(v, med.value());
522 const String& smi_str = String::Handle(String::New("1"));
523 const String& mint1_str = String::Handle(String::New("2147419168"));
524 const String& mint2_str = String::Handle(String::New("-2147419168"));
526 EXPECT(i.IsSmi());
527 i = Integer::NewCanonical(mint1_str);
528 EXPECT(i.IsMint());
529 EXPECT(!i.IsZero());
530 EXPECT(!i.IsNegative());
531 i = Integer::NewCanonical(mint2_str);
532 EXPECT(i.IsMint());
533 EXPECT(!i.IsZero());
534 EXPECT(i.IsNegative());
535 }
537 EXPECT(i.IsMint());
538 EXPECT(!i.IsZero());
539 EXPECT(!i.IsNegative());
541 Mint& i2 = Mint::Handle();
542 i2 ^= Integer::New(DART_2PART_UINT64_C(1010, 0));
543 EXPECT(i1.Equals(i2));
544 EXPECT(!i.Equals(i1));
545 int64_t test = DART_2PART_UINT64_C(1010, 0);
546 EXPECT_EQ(test, i2.value());
547
548 Mint& a = Mint::Handle();
550 Mint& b = Mint::Handle();
552 EXPECT_EQ(1, a.CompareWith(b));
553 EXPECT_EQ(-1, b.CompareWith(a));
554 EXPECT_EQ(0, a.CompareWith(a));
555
556 Mint& c = Mint::Handle();
558 Smi& smi1 = Smi::Handle(Smi::New(4));
559 Smi& smi2 = Smi::Handle(Smi::New(-4));
560 EXPECT_EQ(1, a.CompareWith(smi1));
561 EXPECT_EQ(1, a.CompareWith(smi2));
562 EXPECT_EQ(-1, c.CompareWith(smi1));
563 EXPECT_EQ(-1, c.CompareWith(smi2));
564
565 int64_t mint_value = DART_2PART_UINT64_C(0x7FFFFFFF, 64);
566 const String& mint_string = String::Handle(String::New("0x7FFFFFFF00000064"));
567 Mint& mint1 = Mint::Handle();
568 mint1 ^= Integer::NewCanonical(mint_string);
569 Mint& mint2 = Mint::Handle();
570 mint2 ^= Integer::NewCanonical(mint_string);
571 EXPECT_EQ(mint1.value(), mint_value);
572 EXPECT_EQ(mint2.value(), mint_value);
573 EXPECT_EQ(mint1.ptr(), mint2.ptr());
574#endif
575}
576
578 {
579 const double dbl_const = 5.0;
580 const Double& dbl = Double::Handle(Double::New(dbl_const));
581 Object& dbl_object = Object::Handle(dbl.ptr());
582 EXPECT(dbl.IsDouble());
583 EXPECT(dbl_object.IsDouble());
584 EXPECT_EQ(dbl_const, dbl.value());
585 }
586
587 {
588 const double dbl_const = -5.0;
589 const Double& dbl = Double::Handle(Double::New(dbl_const));
590 Object& dbl_object = Object::Handle(dbl.ptr());
591 EXPECT(dbl.IsDouble());
592 EXPECT(dbl_object.IsDouble());
593 EXPECT_EQ(dbl_const, dbl.value());
594 }
595
596 {
597 const double dbl_const = 0.0;
598 const Double& dbl = Double::Handle(Double::New(dbl_const));
599 Object& dbl_object = Object::Handle(dbl.ptr());
600 EXPECT(dbl.IsDouble());
601 EXPECT(dbl_object.IsDouble());
602 EXPECT_EQ(dbl_const, dbl.value());
603 }
604
605 {
606 const double dbl_const = 5.0;
607 const String& dbl_str = String::Handle(String::New("5.0"));
608 const Double& dbl1 = Double::Handle(Double::NewCanonical(dbl_const));
609 const Double& dbl2 = Double::Handle(Double::NewCanonical(dbl_const));
610 const Double& dbl3 = Double::Handle(Double::NewCanonical(dbl_str));
611 EXPECT_EQ(dbl_const, dbl1.value());
612 EXPECT_EQ(dbl_const, dbl2.value());
613 EXPECT_EQ(dbl_const, dbl3.value());
614 EXPECT_EQ(dbl1.ptr(), dbl2.ptr());
615 EXPECT_EQ(dbl1.ptr(), dbl3.ptr());
616 }
617
618 {
619 const double dbl_const = 2.0;
620 const Double& dbl1 = Double::Handle(Double::New(dbl_const));
621 const Double& dbl2 = Double::Handle(Double::New(dbl_const));
622 EXPECT(dbl1.OperatorEquals(dbl2));
623 EXPECT(dbl1.IsIdenticalTo(dbl2));
624 EXPECT(dbl1.CanonicalizeEquals(dbl2));
625 const Double& dbl3 = Double::Handle(Double::New(3.3));
626 EXPECT(!dbl1.OperatorEquals(dbl3));
629 const Double& nan0 = Double::Handle(Double::New(NAN));
630 EXPECT(isnan(nan0.value()));
631 EXPECT(nan0.IsIdenticalTo(nan0));
632 EXPECT(nan0.CanonicalizeEquals(nan0));
633 EXPECT(!nan0.OperatorEquals(nan0));
634 const Double& nan1 =
635 Double::Handle(Double::New(bit_cast<double>(kMaxUint64 - 0)));
636 const Double& nan2 =
637 Double::Handle(Double::New(bit_cast<double>(kMaxUint64 - 1)));
638 EXPECT(isnan(nan1.value()));
639 EXPECT(isnan(nan2.value()));
640 EXPECT(!nan1.IsIdenticalTo(nan2));
641 EXPECT(!nan1.CanonicalizeEquals(nan2));
642 EXPECT(!nan1.OperatorEquals(nan2));
643 }
644 {
645 const String& dbl_str0 = String::Handle(String::New("bla"));
646 const Double& dbl0 = Double::Handle(Double::New(dbl_str0));
647 EXPECT(dbl0.IsNull());
648
649 const String& dbl_str1 = String::Handle(String::New("2.0"));
650 const Double& dbl1 = Double::Handle(Double::New(dbl_str1));
651 EXPECT_EQ(2.0, dbl1.value());
652
653 // Disallow legacy form.
654 const String& dbl_str2 = String::Handle(String::New("2.0d"));
655 const Double& dbl2 = Double::Handle(Double::New(dbl_str2));
656 EXPECT(dbl2.IsNull());
657 }
658}
659
663 EXPECT(i.IsSmi());
665 EXPECT(i.IsSmi());
667 EXPECT(i.IsSmi());
669 String::Handle(String::New("12345678901234567890")));
670 EXPECT(i.IsNull());
672 String::Handle(String::New("-12345678901234567890111222")));
673 EXPECT(i.IsNull());
674}
675
677 const char* kHello = "Hello World!";
678 int32_t hello_len = strlen(kHello);
679 const String& str = String::Handle(String::New(kHello));
680 EXPECT(str.IsInstance());
681 EXPECT(str.IsString());
682 EXPECT(str.IsOneByteString());
683 EXPECT(!str.IsTwoByteString());
684 EXPECT(!str.IsNumber());
685 EXPECT_EQ(hello_len, str.Length());
686 EXPECT_EQ('H', str.CharAt(0));
687 EXPECT_EQ('e', str.CharAt(1));
688 EXPECT_EQ('l', str.CharAt(2));
689 EXPECT_EQ('l', str.CharAt(3));
690 EXPECT_EQ('o', str.CharAt(4));
691 EXPECT_EQ(' ', str.CharAt(5));
692 EXPECT_EQ('W', str.CharAt(6));
693 EXPECT_EQ('o', str.CharAt(7));
694 EXPECT_EQ('r', str.CharAt(8));
695 EXPECT_EQ('l', str.CharAt(9));
696 EXPECT_EQ('d', str.CharAt(10));
697 EXPECT_EQ('!', str.CharAt(11));
698
699 const uint8_t* motto =
700 reinterpret_cast<const uint8_t*>("Dart's bescht wos je hets gits");
701 const String& str2 = String::Handle(String::FromUTF8(motto + 7, 4));
702 EXPECT_EQ(4, str2.Length());
703 EXPECT_EQ('b', str2.CharAt(0));
704 EXPECT_EQ('e', str2.CharAt(1));
705 EXPECT_EQ('s', str2.CharAt(2));
706 EXPECT_EQ('c', str2.CharAt(3));
707
708 const String& str3 = String::Handle(String::New(kHello));
709 EXPECT(str.Equals(str));
710 EXPECT_EQ(str.Hash(), str.Hash());
711 EXPECT(!str.Equals(str2));
712 EXPECT(str.Equals(str3));
713 EXPECT_EQ(str.Hash(), str3.Hash());
714 EXPECT(str3.Equals(str));
715
716 const String& str4 = String::Handle(String::New("foo"));
717 const String& str5 = String::Handle(String::New("bar"));
718 const String& str6 = String::Handle(String::Concat(str4, str5));
719 const String& str7 = String::Handle(String::New("foobar"));
720 EXPECT(str6.Equals(str7));
721 EXPECT(!str6.Equals(Smi::Handle(Smi::New(4))));
722
723 const String& empty1 = String::Handle(String::New(""));
724 const String& empty2 = String::Handle(String::New(""));
725 EXPECT(empty1.Equals(empty2, 0, 0));
726
727 const intptr_t kCharsLen = 8;
728 const uint8_t chars[kCharsLen] = {1, 2, 127, 64, 92, 0, 55, 55};
729 const String& str8 = String::Handle(String::FromUTF8(chars, kCharsLen));
730 EXPECT_EQ(kCharsLen, str8.Length());
731 EXPECT_EQ(1, str8.CharAt(0));
732 EXPECT_EQ(127, str8.CharAt(2));
733 EXPECT_EQ(64, str8.CharAt(3));
734 EXPECT_EQ(0, str8.CharAt(5));
735 EXPECT_EQ(55, str8.CharAt(6));
736 EXPECT_EQ(55, str8.CharAt(7));
737 const intptr_t kCharsIndex = 3;
738 const String& sub1 = String::Handle(String::SubString(str8, kCharsIndex));
739 EXPECT_EQ((kCharsLen - kCharsIndex), sub1.Length());
740 EXPECT_EQ(64, sub1.CharAt(0));
741 EXPECT_EQ(92, sub1.CharAt(1));
742 EXPECT_EQ(0, sub1.CharAt(2));
743 EXPECT_EQ(55, sub1.CharAt(3));
744 EXPECT_EQ(55, sub1.CharAt(4));
745
746 const intptr_t kWideCharsLen = 7;
747 uint16_t wide_chars[kWideCharsLen] = {'H', 'e', 'l', 'l', 'o', 256, '!'};
748 const String& two_str =
749 String::Handle(String::FromUTF16(wide_chars, kWideCharsLen));
750 EXPECT(two_str.IsInstance());
751 EXPECT(two_str.IsString());
752 EXPECT(two_str.IsTwoByteString());
753 EXPECT(!two_str.IsOneByteString());
754 EXPECT_EQ(kWideCharsLen, two_str.Length());
755 EXPECT_EQ('H', two_str.CharAt(0));
756 EXPECT_EQ(256, two_str.CharAt(5));
757 const intptr_t kWideCharsIndex = 3;
758 const String& sub2 = String::Handle(String::SubString(two_str, kCharsIndex));
759 EXPECT_EQ((kWideCharsLen - kWideCharsIndex), sub2.Length());
760 EXPECT_EQ('l', sub2.CharAt(0));
761 EXPECT_EQ('o', sub2.CharAt(1));
762 EXPECT_EQ(256, sub2.CharAt(2));
763 EXPECT_EQ('!', sub2.CharAt(3));
764
765 {
766 const String& str1 = String::Handle(String::New("My.create"));
767 const String& str2 = String::Handle(String::New("My"));
768 const String& str3 = String::Handle(String::New("create"));
769 EXPECT_EQ(true, str1.StartsWith(str2));
770 EXPECT_EQ(false, str1.StartsWith(str3));
771 }
772
773 const int32_t four_chars[] = {'C', 0xFF, 'h', 0xFFFF, 'a', 0x10FFFF, 'r'};
774 const String& four_str = String::Handle(String::FromUTF32(four_chars, 7));
775 EXPECT_EQ(four_str.Hash(), four_str.Hash());
776 EXPECT(four_str.IsTwoByteString());
777 EXPECT(!four_str.IsOneByteString());
778 EXPECT_EQ(8, four_str.Length());
779 EXPECT_EQ('C', four_str.CharAt(0));
780 EXPECT_EQ(0xFF, four_str.CharAt(1));
781 EXPECT_EQ('h', four_str.CharAt(2));
782 EXPECT_EQ(0xFFFF, four_str.CharAt(3));
783 EXPECT_EQ('a', four_str.CharAt(4));
784 EXPECT_EQ(0xDBFF, four_str.CharAt(5));
785 EXPECT_EQ(0xDFFF, four_str.CharAt(6));
786 EXPECT_EQ('r', four_str.CharAt(7));
787
788 // Create a 1-byte string from an array of 2-byte elements.
789 {
790 const uint16_t char16[] = {0x00, 0x7F, 0xFF};
791 const String& str8 = String::Handle(String::FromUTF16(char16, 3));
792 EXPECT(str8.IsOneByteString());
793 EXPECT(!str8.IsTwoByteString());
794 EXPECT_EQ(0x00, str8.CharAt(0));
795 EXPECT_EQ(0x7F, str8.CharAt(1));
796 EXPECT_EQ(0xFF, str8.CharAt(2));
797 }
798
799 // Create a 1-byte string from an array of 4-byte elements.
800 {
801 const int32_t char32[] = {0x00, 0x1F, 0x7F};
802 const String& str8 = String::Handle(String::FromUTF32(char32, 3));
803 EXPECT(str8.IsOneByteString());
804 EXPECT(!str8.IsTwoByteString());
805 EXPECT_EQ(0x00, str8.CharAt(0));
806 EXPECT_EQ(0x1F, str8.CharAt(1));
807 EXPECT_EQ(0x7F, str8.CharAt(2));
808 }
809
810 // Create a 2-byte string from an array of 4-byte elements.
811 {
812 const int32_t char32[] = {0, 0x7FFF, 0xFFFF};
813 const String& str16 = String::Handle(String::FromUTF32(char32, 3));
814 EXPECT(!str16.IsOneByteString());
815 EXPECT(str16.IsTwoByteString());
816 EXPECT_EQ(0x0000, str16.CharAt(0));
817 EXPECT_EQ(0x7FFF, str16.CharAt(1));
818 EXPECT_EQ(0xFFFF, str16.CharAt(2));
819 }
820}
821
823 const char* hello_str = "Hello World!";
824 const String& str =
825 String::Handle(String::NewFormatted("Hello %s!", "World"));
826 EXPECT(str.IsInstance());
827 EXPECT(str.IsString());
828 EXPECT(str.IsOneByteString());
829 EXPECT(!str.IsTwoByteString());
830 EXPECT(!str.IsNumber());
831 EXPECT(str.Equals(hello_str));
832}
833
835 // Create strings from concatenated 1-byte empty strings.
836 {
837 const String& empty1 = String::Handle(String::New(""));
838 EXPECT(empty1.IsOneByteString());
839 EXPECT_EQ(0, empty1.Length());
840
841 const String& empty2 = String::Handle(String::New(""));
842 EXPECT(empty2.IsOneByteString());
843 EXPECT_EQ(0, empty2.Length());
844
845 // Concat
846
847 const String& empty3 = String::Handle(String::Concat(empty1, empty2));
848 EXPECT(empty3.IsOneByteString());
849 EXPECT_EQ(0, empty3.Length());
850
851 // ConcatAll
852
853 const Array& array1 = Array::Handle(Array::New(0));
854 EXPECT_EQ(0, array1.Length());
855 const String& empty4 = String::Handle(String::ConcatAll(array1));
856 EXPECT_EQ(0, empty4.Length());
857
858 const Array& array2 = Array::Handle(Array::New(10));
859 EXPECT_EQ(10, array2.Length());
860 for (int i = 0; i < array2.Length(); ++i) {
861 array2.SetAt(i, String::Handle(String::New("")));
862 }
863 const String& empty5 = String::Handle(String::ConcatAll(array2));
864 EXPECT(empty5.IsOneByteString());
865 EXPECT_EQ(0, empty5.Length());
866
867 const Array& array3 = Array::Handle(Array::New(123));
868 EXPECT_EQ(123, array3.Length());
869
870 const String& empty6 = String::Handle(String::New(""));
871 EXPECT(empty6.IsOneByteString());
872 EXPECT_EQ(0, empty6.Length());
873 for (int i = 0; i < array3.Length(); ++i) {
874 array3.SetAt(i, empty6);
875 }
876 const String& empty7 = String::Handle(String::ConcatAll(array3));
877 EXPECT(empty7.IsOneByteString());
878 EXPECT_EQ(0, empty7.Length());
879 }
880
881 // Concatenated empty and non-empty 1-byte strings.
882 {
883 const String& str1 = String::Handle(String::New(""));
884 EXPECT_EQ(0, str1.Length());
885 EXPECT(str1.IsOneByteString());
886
887 const String& str2 = String::Handle(String::New("one"));
888 EXPECT(str2.IsOneByteString());
889 EXPECT_EQ(3, str2.Length());
890
891 // Concat
892
893 const String& str3 = String::Handle(String::Concat(str1, str2));
894 EXPECT(str3.IsOneByteString());
895 EXPECT_EQ(3, str3.Length());
896 EXPECT(str3.Equals(str2));
897
898 const String& str4 = String::Handle(String::Concat(str2, str1));
899 EXPECT(str4.IsOneByteString());
900 EXPECT_EQ(3, str4.Length());
901 EXPECT(str4.Equals(str2));
902
903 // ConcatAll
904
905 const Array& array1 = Array::Handle(Array::New(2));
906 EXPECT_EQ(2, array1.Length());
907 array1.SetAt(0, str1);
908 array1.SetAt(1, str2);
909 const String& str5 = String::Handle(String::ConcatAll(array1));
910 EXPECT(str5.IsOneByteString());
911 EXPECT_EQ(3, str5.Length());
912 EXPECT(str5.Equals(str2));
913
914 const Array& array2 = Array::Handle(Array::New(2));
915 EXPECT_EQ(2, array2.Length());
916 array2.SetAt(0, str1);
917 array2.SetAt(1, str2);
918 const String& str6 = String::Handle(String::ConcatAll(array2));
919 EXPECT(str6.IsOneByteString());
920 EXPECT_EQ(3, str6.Length());
921 EXPECT(str6.Equals(str2));
922
923 const Array& array3 = Array::Handle(Array::New(3));
924 EXPECT_EQ(3, array3.Length());
925 array3.SetAt(0, str2);
926 array3.SetAt(1, str1);
927 array3.SetAt(2, str2);
928 const String& str7 = String::Handle(String::ConcatAll(array3));
929 EXPECT(str7.IsOneByteString());
930 EXPECT_EQ(6, str7.Length());
931 EXPECT(str7.Equals("oneone"));
932 EXPECT(!str7.Equals("oneoneone"));
933 }
934
935 // Create a string by concatenating non-empty 1-byte strings.
936 {
937 const char* one = "one";
938 intptr_t one_len = strlen(one);
939 const String& onestr = String::Handle(String::New(one));
940 EXPECT(onestr.IsOneByteString());
941 EXPECT_EQ(one_len, onestr.Length());
942
943 const char* three = "three";
944 intptr_t three_len = strlen(three);
945 const String& threestr = String::Handle(String::New(three));
946 EXPECT(threestr.IsOneByteString());
947 EXPECT_EQ(three_len, threestr.Length());
948
949 // Concat
950
951 const String& str3 = String::Handle(String::Concat(onestr, threestr));
952 EXPECT(str3.IsOneByteString());
953 const char* one_three = "onethree";
954 EXPECT(str3.Equals(one_three));
955
956 const String& str4 = String::Handle(String::Concat(threestr, onestr));
957 EXPECT(str4.IsOneByteString());
958 const char* three_one = "threeone";
959 intptr_t three_one_len = strlen(three_one);
960 EXPECT_EQ(three_one_len, str4.Length());
961 EXPECT(str4.Equals(three_one));
962
963 // ConcatAll
964
965 const Array& array1 = Array::Handle(Array::New(2));
966 EXPECT_EQ(2, array1.Length());
967 array1.SetAt(0, onestr);
968 array1.SetAt(1, threestr);
969 const String& str5 = String::Handle(String::ConcatAll(array1));
970 EXPECT(str5.IsOneByteString());
971 intptr_t one_three_len = strlen(one_three);
972 EXPECT_EQ(one_three_len, str5.Length());
973 EXPECT(str5.Equals(one_three));
974
975 const Array& array2 = Array::Handle(Array::New(2));
976 EXPECT_EQ(2, array2.Length());
977 array2.SetAt(0, threestr);
978 array2.SetAt(1, onestr);
979 const String& str6 = String::Handle(String::ConcatAll(array2));
980 EXPECT(str6.IsOneByteString());
981 EXPECT_EQ(three_one_len, str6.Length());
982 EXPECT(str6.Equals(three_one));
983
984 const Array& array3 = Array::Handle(Array::New(3));
985 EXPECT_EQ(3, array3.Length());
986 array3.SetAt(0, onestr);
987 array3.SetAt(1, threestr);
988 array3.SetAt(2, onestr);
989 const String& str7 = String::Handle(String::ConcatAll(array3));
990 EXPECT(str7.IsOneByteString());
991 const char* one_three_one = "onethreeone";
992 intptr_t one_three_one_len = strlen(one_three_one);
993 EXPECT_EQ(one_three_one_len, str7.Length());
994 EXPECT(str7.Equals(one_three_one));
995
996 const Array& array4 = Array::Handle(Array::New(3));
997 EXPECT_EQ(3, array4.Length());
998 array4.SetAt(0, threestr);
999 array4.SetAt(1, onestr);
1000 array4.SetAt(2, threestr);
1001 const String& str8 = String::Handle(String::ConcatAll(array4));
1002 EXPECT(str8.IsOneByteString());
1003 const char* three_one_three = "threeonethree";
1004 intptr_t three_one_three_len = strlen(three_one_three);
1005 EXPECT_EQ(three_one_three_len, str8.Length());
1006 EXPECT(str8.Equals(three_one_three));
1007 }
1008
1009 // Concatenate empty and non-empty 2-byte strings.
1010 {
1011 const String& str1 = String::Handle(String::New(""));
1012 EXPECT(str1.IsOneByteString());
1013 EXPECT_EQ(0, str1.Length());
1014
1015 uint16_t two[] = {0x05E6, 0x05D5, 0x05D5, 0x05D9, 0x05D9};
1016 intptr_t two_len = sizeof(two) / sizeof(two[0]);
1017 const String& str2 = String::Handle(String::FromUTF16(two, two_len));
1018 EXPECT(str2.IsTwoByteString());
1019 EXPECT_EQ(two_len, str2.Length());
1020
1021 // Concat
1022
1023 const String& str3 = String::Handle(String::Concat(str1, str2));
1024 EXPECT(str3.IsTwoByteString());
1025 EXPECT_EQ(two_len, str3.Length());
1026 EXPECT(str3.Equals(str2));
1027
1028 const String& str4 = String::Handle(String::Concat(str2, str1));
1029 EXPECT(str4.IsTwoByteString());
1030 EXPECT_EQ(two_len, str4.Length());
1031 EXPECT(str4.Equals(str2));
1032
1033 // ConcatAll
1034
1035 const Array& array1 = Array::Handle(Array::New(2));
1036 EXPECT_EQ(2, array1.Length());
1037 array1.SetAt(0, str1);
1038 array1.SetAt(1, str2);
1039 const String& str5 = String::Handle(String::ConcatAll(array1));
1040 EXPECT(str5.IsTwoByteString());
1041 EXPECT_EQ(two_len, str5.Length());
1042 EXPECT(str5.Equals(str2));
1043
1044 const Array& array2 = Array::Handle(Array::New(2));
1045 EXPECT_EQ(2, array2.Length());
1046 array2.SetAt(0, str1);
1047 array2.SetAt(1, str2);
1048 const String& str6 = String::Handle(String::ConcatAll(array2));
1049 EXPECT(str6.IsTwoByteString());
1050 EXPECT_EQ(two_len, str6.Length());
1051 EXPECT(str6.Equals(str2));
1052
1053 const Array& array3 = Array::Handle(Array::New(3));
1054 EXPECT_EQ(3, array3.Length());
1055 array3.SetAt(0, str2);
1056 array3.SetAt(1, str1);
1057 array3.SetAt(2, str2);
1058 const String& str7 = String::Handle(String::ConcatAll(array3));
1059 EXPECT(str7.IsTwoByteString());
1060 EXPECT_EQ(two_len * 2, str7.Length());
1061 uint16_t twotwo[] = {0x05E6, 0x05D5, 0x05D5, 0x05D9, 0x05D9,
1062 0x05E6, 0x05D5, 0x05D5, 0x05D9, 0x05D9};
1063 intptr_t twotwo_len = sizeof(twotwo) / sizeof(twotwo[0]);
1064 EXPECT(str7.IsTwoByteString());
1065 EXPECT(str7.Equals(twotwo, twotwo_len));
1066 }
1067
1068 // Concatenating non-empty 2-byte strings.
1069 {
1070 const uint16_t one[] = {0x05D0, 0x05D9, 0x05D9, 0x05DF};
1071 intptr_t one_len = sizeof(one) / sizeof(one[0]);
1072 const String& str1 = String::Handle(String::FromUTF16(one, one_len));
1073 EXPECT(str1.IsTwoByteString());
1074 EXPECT_EQ(one_len, str1.Length());
1075
1076 const uint16_t two[] = {0x05E6, 0x05D5, 0x05D5, 0x05D9, 0x05D9};
1077 intptr_t two_len = sizeof(two) / sizeof(two[0]);
1078 const String& str2 = String::Handle(String::FromUTF16(two, two_len));
1079 EXPECT(str2.IsTwoByteString());
1080 EXPECT_EQ(two_len, str2.Length());
1081
1082 // Concat
1083
1084 const String& one_two_str = String::Handle(String::Concat(str1, str2));
1085 EXPECT(one_two_str.IsTwoByteString());
1086 const uint16_t one_two[] = {0x05D0, 0x05D9, 0x05D9, 0x05DF, 0x05E6,
1087 0x05D5, 0x05D5, 0x05D9, 0x05D9};
1088 intptr_t one_two_len = sizeof(one_two) / sizeof(one_two[0]);
1089 EXPECT_EQ(one_two_len, one_two_str.Length());
1090 EXPECT(one_two_str.Equals(one_two, one_two_len));
1091
1092 const String& two_one_str = String::Handle(String::Concat(str2, str1));
1093 EXPECT(two_one_str.IsTwoByteString());
1094 const uint16_t two_one[] = {0x05E6, 0x05D5, 0x05D5, 0x05D9, 0x05D9,
1095 0x05D0, 0x05D9, 0x05D9, 0x05DF};
1096 intptr_t two_one_len = sizeof(two_one) / sizeof(two_one[0]);
1097 EXPECT_EQ(two_one_len, two_one_str.Length());
1098 EXPECT(two_one_str.Equals(two_one, two_one_len));
1099
1100 // ConcatAll
1101
1102 const Array& array1 = Array::Handle(Array::New(2));
1103 EXPECT_EQ(2, array1.Length());
1104 array1.SetAt(0, str1);
1105 array1.SetAt(1, str2);
1106 const String& str3 = String::Handle(String::ConcatAll(array1));
1107 EXPECT(str3.IsTwoByteString());
1108 EXPECT_EQ(one_two_len, str3.Length());
1109 EXPECT(str3.Equals(one_two, one_two_len));
1110
1111 const Array& array2 = Array::Handle(Array::New(2));
1112 EXPECT_EQ(2, array2.Length());
1113 array2.SetAt(0, str2);
1114 array2.SetAt(1, str1);
1115 const String& str4 = String::Handle(String::ConcatAll(array2));
1116 EXPECT(str4.IsTwoByteString());
1117 EXPECT_EQ(two_one_len, str4.Length());
1118 EXPECT(str4.Equals(two_one, two_one_len));
1119
1120 const Array& array3 = Array::Handle(Array::New(3));
1121 EXPECT_EQ(3, array3.Length());
1122 array3.SetAt(0, str1);
1123 array3.SetAt(1, str2);
1124 array3.SetAt(2, str1);
1125 const String& str5 = String::Handle(String::ConcatAll(array3));
1126 EXPECT(str5.IsTwoByteString());
1127 const uint16_t one_two_one[] = {0x05D0, 0x05D9, 0x05D9, 0x05DF, 0x05E6,
1128 0x05D5, 0x05D5, 0x05D9, 0x05D9, 0x05D0,
1129 0x05D9, 0x05D9, 0x05DF};
1130 intptr_t one_two_one_len = sizeof(one_two_one) / sizeof(one_two_one[0]);
1131 EXPECT_EQ(one_two_one_len, str5.Length());
1132 EXPECT(str5.Equals(one_two_one, one_two_one_len));
1133
1134 const Array& array4 = Array::Handle(Array::New(3));
1135 EXPECT_EQ(3, array4.Length());
1136 array4.SetAt(0, str2);
1137 array4.SetAt(1, str1);
1138 array4.SetAt(2, str2);
1139 const String& str6 = String::Handle(String::ConcatAll(array4));
1140 EXPECT(str6.IsTwoByteString());
1141 const uint16_t two_one_two[] = {0x05E6, 0x05D5, 0x05D5, 0x05D9, 0x05D9,
1142 0x05D0, 0x05D9, 0x05D9, 0x05DF, 0x05E6,
1143 0x05D5, 0x05D5, 0x05D9, 0x05D9};
1144 intptr_t two_one_two_len = sizeof(two_one_two) / sizeof(two_one_two[0]);
1145 EXPECT_EQ(two_one_two_len, str6.Length());
1146 EXPECT(str6.Equals(two_one_two, two_one_two_len));
1147 }
1148
1149 // Concatenated empty and non-empty strings built from 4-byte elements.
1150 {
1151 const String& str1 = String::Handle(String::New(""));
1152 EXPECT(str1.IsOneByteString());
1153 EXPECT_EQ(0, str1.Length());
1154
1155 int32_t four[] = {0x1D4D5, 0x1D4DE, 0x1D4E4, 0x1D4E1};
1156 intptr_t four_len = sizeof(four) / sizeof(four[0]);
1157 intptr_t expected_len = (four_len * 2);
1158 const String& str2 = String::Handle(String::FromUTF32(four, four_len));
1159 EXPECT(str2.IsTwoByteString());
1160 EXPECT_EQ(expected_len, str2.Length());
1161
1162 // Concat
1163
1164 const String& str3 = String::Handle(String::Concat(str1, str2));
1165 EXPECT_EQ(expected_len, str3.Length());
1166 EXPECT(str3.Equals(str2));
1167
1168 const String& str4 = String::Handle(String::Concat(str2, str1));
1169 EXPECT(str4.IsTwoByteString());
1170 EXPECT_EQ(expected_len, str4.Length());
1171 EXPECT(str4.Equals(str2));
1172
1173 // ConcatAll
1174
1175 const Array& array1 = Array::Handle(Array::New(2));
1176 EXPECT_EQ(2, array1.Length());
1177 array1.SetAt(0, str1);
1178 array1.SetAt(1, str2);
1179 const String& str5 = String::Handle(String::ConcatAll(array1));
1180 EXPECT(str5.IsTwoByteString());
1181 EXPECT_EQ(expected_len, str5.Length());
1182 EXPECT(str5.Equals(str2));
1183
1184 const Array& array2 = Array::Handle(Array::New(2));
1185 EXPECT_EQ(2, array2.Length());
1186 array2.SetAt(0, str1);
1187 array2.SetAt(1, str2);
1188 const String& str6 = String::Handle(String::ConcatAll(array2));
1189 EXPECT(str6.IsTwoByteString());
1190 EXPECT_EQ(expected_len, str6.Length());
1191 EXPECT(str6.Equals(str2));
1192
1193 const Array& array3 = Array::Handle(Array::New(3));
1194 EXPECT_EQ(3, array3.Length());
1195 array3.SetAt(0, str2);
1196 array3.SetAt(1, str1);
1197 array3.SetAt(2, str2);
1198 const String& str7 = String::Handle(String::ConcatAll(array3));
1199 EXPECT(str7.IsTwoByteString());
1200 int32_t fourfour[] = {0x1D4D5, 0x1D4DE, 0x1D4E4, 0x1D4E1,
1201 0x1D4D5, 0x1D4DE, 0x1D4E4, 0x1D4E1};
1202 intptr_t fourfour_len = sizeof(fourfour) / sizeof(fourfour[0]);
1203 EXPECT_EQ((fourfour_len * 2), str7.Length());
1204 const String& fourfour_str =
1205 String::Handle(String::FromUTF32(fourfour, fourfour_len));
1206 EXPECT(str7.Equals(fourfour_str));
1207 }
1208
1209 // Concatenate non-empty strings built from 4-byte elements.
1210 {
1211 const int32_t one[] = {0x105D0, 0x105D9, 0x105D9, 0x105DF};
1212 intptr_t one_len = sizeof(one) / sizeof(one[0]);
1213 const String& onestr = String::Handle(String::FromUTF32(one, one_len));
1214 EXPECT(onestr.IsTwoByteString());
1215 EXPECT_EQ((one_len * 2), onestr.Length());
1216
1217 const int32_t two[] = {0x105E6, 0x105D5, 0x105D5, 0x105D9, 0x105D9};
1218 intptr_t two_len = sizeof(two) / sizeof(two[0]);
1219 const String& twostr = String::Handle(String::FromUTF32(two, two_len));
1220 EXPECT(twostr.IsTwoByteString());
1221 EXPECT_EQ((two_len * 2), twostr.Length());
1222
1223 // Concat
1224
1225 const String& str1 = String::Handle(String::Concat(onestr, twostr));
1226 EXPECT(str1.IsTwoByteString());
1227 const int32_t one_two[] = {0x105D0, 0x105D9, 0x105D9, 0x105DF, 0x105E6,
1228 0x105D5, 0x105D5, 0x105D9, 0x105D9};
1229 intptr_t one_two_len = sizeof(one_two) / sizeof(one_two[0]);
1230 EXPECT_EQ((one_two_len * 2), str1.Length());
1231 const String& one_two_str =
1232 String::Handle(String::FromUTF32(one_two, one_two_len));
1233 EXPECT(str1.Equals(one_two_str));
1234
1235 const String& str2 = String::Handle(String::Concat(twostr, onestr));
1236 EXPECT(str2.IsTwoByteString());
1237 const int32_t two_one[] = {0x105E6, 0x105D5, 0x105D5, 0x105D9, 0x105D9,
1238 0x105D0, 0x105D9, 0x105D9, 0x105DF};
1239 intptr_t two_one_len = sizeof(two_one) / sizeof(two_one[0]);
1240 EXPECT_EQ((two_one_len * 2), str2.Length());
1241 const String& two_one_str =
1242 String::Handle(String::FromUTF32(two_one, two_one_len));
1243 EXPECT(str2.Equals(two_one_str));
1244
1245 // ConcatAll
1246
1247 const Array& array1 = Array::Handle(Array::New(2));
1248 EXPECT_EQ(2, array1.Length());
1249 array1.SetAt(0, onestr);
1250 array1.SetAt(1, twostr);
1251 const String& str3 = String::Handle(String::ConcatAll(array1));
1252 EXPECT(str3.IsTwoByteString());
1253 EXPECT_EQ((one_two_len * 2), str3.Length());
1254 EXPECT(str3.Equals(one_two_str));
1255
1256 const Array& array2 = Array::Handle(Array::New(2));
1257 EXPECT_EQ(2, array2.Length());
1258 array2.SetAt(0, twostr);
1259 array2.SetAt(1, onestr);
1260 const String& str4 = String::Handle(String::ConcatAll(array2));
1261 EXPECT(str4.IsTwoByteString());
1262 EXPECT_EQ((two_one_len * 2), str4.Length());
1263 EXPECT(str4.Equals(two_one_str));
1264
1265 const Array& array3 = Array::Handle(Array::New(3));
1266 EXPECT_EQ(3, array3.Length());
1267 array3.SetAt(0, onestr);
1268 array3.SetAt(1, twostr);
1269 array3.SetAt(2, onestr);
1270 const String& str5 = String::Handle(String::ConcatAll(array3));
1271 EXPECT(str5.IsTwoByteString());
1272 const int32_t one_two_one[] = {0x105D0, 0x105D9, 0x105D9, 0x105DF, 0x105E6,
1273 0x105D5, 0x105D5, 0x105D9, 0x105D9, 0x105D0,
1274 0x105D9, 0x105D9, 0x105DF};
1275 intptr_t one_two_one_len = sizeof(one_two_one) / sizeof(one_two_one[0]);
1276 EXPECT_EQ((one_two_one_len * 2), str5.Length());
1277 const String& one_two_one_str =
1278 String::Handle(String::FromUTF32(one_two_one, one_two_one_len));
1279 EXPECT(str5.Equals(one_two_one_str));
1280
1281 const Array& array4 = Array::Handle(Array::New(3));
1282 EXPECT_EQ(3, array4.Length());
1283 array4.SetAt(0, twostr);
1284 array4.SetAt(1, onestr);
1285 array4.SetAt(2, twostr);
1286 const String& str6 = String::Handle(String::ConcatAll(array4));
1287 EXPECT(str6.IsTwoByteString());
1288 const int32_t two_one_two[] = {0x105E6, 0x105D5, 0x105D5, 0x105D9, 0x105D9,
1289 0x105D0, 0x105D9, 0x105D9, 0x105DF, 0x105E6,
1290 0x105D5, 0x105D5, 0x105D9, 0x105D9};
1291 intptr_t two_one_two_len = sizeof(two_one_two) / sizeof(two_one_two[0]);
1292 EXPECT_EQ((two_one_two_len * 2), str6.Length());
1293 const String& two_one_two_str =
1294 String::Handle(String::FromUTF32(two_one_two, two_one_two_len));
1295 EXPECT(str6.Equals(two_one_two_str));
1296 }
1297
1298 // Concatenate 1-byte strings and 2-byte strings.
1299 {
1300 const uint8_t one[] = {'o', 'n', 'e', ' ', 'b', 'y', 't', 'e'};
1301 intptr_t one_len = sizeof(one) / sizeof(one[0]);
1302 const String& onestr = String::Handle(String::FromLatin1(one, one_len));
1303 EXPECT(onestr.IsOneByteString());
1304 EXPECT_EQ(one_len, onestr.Length());
1305 EXPECT(onestr.EqualsLatin1(one, one_len));
1306
1307 uint16_t two[] = {0x05E6, 0x05D5, 0x05D5, 0x05D9, 0x05D9};
1308 intptr_t two_len = sizeof(two) / sizeof(two[0]);
1309 const String& twostr = String::Handle(String::FromUTF16(two, two_len));
1310 EXPECT(twostr.IsTwoByteString());
1311 EXPECT_EQ(two_len, twostr.Length());
1312 EXPECT(twostr.Equals(two, two_len));
1313
1314 // Concat
1315
1316 const String& one_two_str = String::Handle(String::Concat(onestr, twostr));
1317 EXPECT(one_two_str.IsTwoByteString());
1318 uint16_t one_two[] = {'o', 'n', 'e', ' ', 'b', 'y', 't',
1319 'e', 0x05E6, 0x05D5, 0x05D5, 0x05D9, 0x05D9};
1320 intptr_t one_two_len = sizeof(one_two) / sizeof(one_two[0]);
1321 EXPECT_EQ(one_two_len, one_two_str.Length());
1322 EXPECT(one_two_str.Equals(one_two, one_two_len));
1323
1324 const String& two_one_str = String::Handle(String::Concat(twostr, onestr));
1325 EXPECT(two_one_str.IsTwoByteString());
1326 uint16_t two_one[] = {0x05E6, 0x05D5, 0x05D5, 0x05D9, 0x05D9, 'o', 'n',
1327 'e', ' ', 'b', 'y', 't', 'e'};
1328 intptr_t two_one_len = sizeof(two_one) / sizeof(two_one[0]);
1329 EXPECT_EQ(two_one_len, two_one_str.Length());
1330 EXPECT(two_one_str.Equals(two_one, two_one_len));
1331
1332 // ConcatAll
1333
1334 const Array& array1 = Array::Handle(Array::New(3));
1335 EXPECT_EQ(3, array1.Length());
1336 array1.SetAt(0, onestr);
1337 array1.SetAt(1, twostr);
1338 array1.SetAt(2, onestr);
1339 const String& one_two_one_str = String::Handle(String::ConcatAll(array1));
1340 EXPECT(one_two_one_str.IsTwoByteString());
1341 EXPECT_EQ(onestr.Length() * 2 + twostr.Length(), one_two_one_str.Length());
1342 uint16_t one_two_one[] = {'o', 'n', 'e', ' ', 'b', 'y', 't',
1343 'e', 0x05E6, 0x05D5, 0x05D5, 0x05D9, 0x05D9, 'o',
1344 'n', 'e', ' ', 'b', 'y', 't', 'e'};
1345 intptr_t one_two_one_len = sizeof(one_two_one) / sizeof(one_two_one[0]);
1346 EXPECT(one_two_one_str.Equals(one_two_one, one_two_one_len));
1347
1348 const Array& array2 = Array::Handle(Array::New(3));
1349 EXPECT_EQ(3, array2.Length());
1350 array2.SetAt(0, twostr);
1351 array2.SetAt(1, onestr);
1352 array2.SetAt(2, twostr);
1353 const String& two_one_two_str = String::Handle(String::ConcatAll(array2));
1354 EXPECT(two_one_two_str.IsTwoByteString());
1355 EXPECT_EQ(twostr.Length() * 2 + onestr.Length(), two_one_two_str.Length());
1356 uint16_t two_one_two[] = {0x05E6, 0x05D5, 0x05D5, 0x05D9, 0x05D9, 'o',
1357 'n', 'e', ' ', 'b', 'y', 't',
1358 'e', 0x05E6, 0x05D5, 0x05D5, 0x05D9, 0x05D9};
1359 intptr_t two_one_two_len = sizeof(two_one_two) / sizeof(two_one_two[0]);
1360 EXPECT(two_one_two_str.Equals(two_one_two, two_one_two_len));
1361 }
1362}
1363
1364ISOLATE_UNIT_TEST_CASE(StringHashConcat) {
1365 EXPECT_EQ(String::Handle(String::New("onebyte")).Hash(),
1367 String::Handle(String::New("byte"))));
1368 uint16_t clef_utf16[] = {0xD834, 0xDD1E};
1369 const String& clef = String::Handle(String::FromUTF16(clef_utf16, 2));
1370 int32_t clef_utf32[] = {0x1D11E};
1371 EXPECT(clef.Equals(clef_utf32, 1));
1372 uword hash32 = String::Hash(String::FromUTF32(clef_utf32, 1));
1373 EXPECT_EQ(hash32, clef.Hash());
1374 EXPECT_EQ(hash32, String::HashConcat(
1375 String::Handle(String::FromUTF16(clef_utf16, 1)),
1376 String::Handle(String::FromUTF16(clef_utf16 + 1, 1))));
1377}
1378
1379ISOLATE_UNIT_TEST_CASE(StringSubStringDifferentWidth) {
1380 // Create 1-byte substring from a 1-byte source string.
1381 const char* onechars = "\xC3\xB6\xC3\xB1\xC3\xA9";
1382
1383 const String& onestr = String::Handle(String::New(onechars));
1384 EXPECT(!onestr.IsNull());
1385 EXPECT(onestr.IsOneByteString());
1386 EXPECT(!onestr.IsTwoByteString());
1387
1388 const String& onesub = String::Handle(String::SubString(onestr, 0));
1389 EXPECT(!onesub.IsNull());
1390 EXPECT(onestr.IsOneByteString());
1391 EXPECT(!onestr.IsTwoByteString());
1392 EXPECT_EQ(onesub.Length(), 3);
1393
1394 // Create 1- and 2-byte substrings from a 2-byte source string.
1395 const char* twochars =
1396 "\x1f\x2f\x3f"
1397 "\xE1\xB9\xAB\xE1\xBA\x85\xE1\xB9\x93";
1398
1399 const String& twostr = String::Handle(String::New(twochars));
1400 EXPECT(!twostr.IsNull());
1401 EXPECT(twostr.IsTwoByteString());
1402
1403 const String& twosub1 = String::Handle(String::SubString(twostr, 0, 3));
1404 EXPECT(!twosub1.IsNull());
1405 EXPECT(twosub1.IsOneByteString());
1406 EXPECT_EQ(twosub1.Length(), 3);
1407
1408 const String& twosub2 = String::Handle(String::SubString(twostr, 3));
1409 EXPECT(!twosub2.IsNull());
1410 EXPECT(twosub2.IsTwoByteString());
1411 EXPECT_EQ(twosub2.Length(), 3);
1412
1413 // Create substrings from a string built using 1-, 2- and 4-byte elements.
1414 const char* fourchars =
1415 "\x1f\x2f\x3f"
1416 "\xE1\xB9\xAB\xE1\xBA\x85\xE1\xB9\x93"
1417 "\xF0\x9D\x96\xBF\xF0\x9D\x97\x88\xF0\x9D\x97\x8E\xF0\x9D\x97\x8B";
1418
1419 const String& fourstr = String::Handle(String::New(fourchars));
1420 EXPECT(!fourstr.IsNull());
1421 EXPECT(fourstr.IsTwoByteString());
1422
1423 const String& foursub1 = String::Handle(String::SubString(fourstr, 0, 3));
1424 EXPECT(!foursub1.IsNull());
1425 EXPECT(foursub1.IsOneByteString());
1426 EXPECT_EQ(foursub1.Length(), 3);
1427
1428 const String& foursub2 = String::Handle(String::SubString(fourstr, 3, 3));
1429 EXPECT(!foursub2.IsNull());
1430 EXPECT(foursub2.IsTwoByteString());
1431 EXPECT_EQ(foursub2.Length(), 3);
1432
1433 const String& foursub4 = String::Handle(String::SubString(fourstr, 6));
1434 EXPECT_EQ(foursub4.Length(), 8);
1435 EXPECT(!foursub4.IsNull());
1436 EXPECT(foursub4.IsTwoByteString());
1437}
1438
1439ISOLATE_UNIT_TEST_CASE(StringFromUtf8Literal) {
1440 // Create a 1-byte string from a UTF-8 encoded string literal.
1441 {
1442 const char* src =
1443 "\xC2\xA0\xC2\xA1\xC2\xA2\xC2\xA3"
1444 "\xC2\xA4\xC2\xA5\xC2\xA6\xC2\xA7"
1445 "\xC2\xA8\xC2\xA9\xC2\xAA\xC2\xAB"
1446 "\xC2\xAC\xC2\xAD\xC2\xAE\xC2\xAF"
1447 "\xC2\xB0\xC2\xB1\xC2\xB2\xC2\xB3"
1448 "\xC2\xB4\xC2\xB5\xC2\xB6\xC2\xB7"
1449 "\xC2\xB8\xC2\xB9\xC2\xBA\xC2\xBB"
1450 "\xC2\xBC\xC2\xBD\xC2\xBE\xC2\xBF"
1451 "\xC3\x80\xC3\x81\xC3\x82\xC3\x83"
1452 "\xC3\x84\xC3\x85\xC3\x86\xC3\x87"
1453 "\xC3\x88\xC3\x89\xC3\x8A\xC3\x8B"
1454 "\xC3\x8C\xC3\x8D\xC3\x8E\xC3\x8F"
1455 "\xC3\x90\xC3\x91\xC3\x92\xC3\x93"
1456 "\xC3\x94\xC3\x95\xC3\x96\xC3\x97"
1457 "\xC3\x98\xC3\x99\xC3\x9A\xC3\x9B"
1458 "\xC3\x9C\xC3\x9D\xC3\x9E\xC3\x9F"
1459 "\xC3\xA0\xC3\xA1\xC3\xA2\xC3\xA3"
1460 "\xC3\xA4\xC3\xA5\xC3\xA6\xC3\xA7"
1461 "\xC3\xA8\xC3\xA9\xC3\xAA\xC3\xAB"
1462 "\xC3\xAC\xC3\xAD\xC3\xAE\xC3\xAF"
1463 "\xC3\xB0\xC3\xB1\xC3\xB2\xC3\xB3"
1464 "\xC3\xB4\xC3\xB5\xC3\xB6\xC3\xB7"
1465 "\xC3\xB8\xC3\xB9\xC3\xBA\xC3\xBB"
1466 "\xC3\xBC\xC3\xBD\xC3\xBE\xC3\xBF";
1467 const uint8_t expected[] = {
1468 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB,
1469 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7,
1470 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xC0, 0xC1, 0xC2, 0xC3,
1471 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
1472 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB,
1473 0xDC, 0xDD, 0xDE, 0xDF, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
1474 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3,
1475 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF,
1476 };
1477 const String& str = String::Handle(String::New(src));
1478 EXPECT(str.IsOneByteString());
1479 intptr_t expected_length = sizeof(expected);
1480 EXPECT_EQ(expected_length, str.Length());
1481 for (int i = 0; i < str.Length(); ++i) {
1482 EXPECT_EQ(expected[i], str.CharAt(i));
1483 }
1484 }
1485
1486 // Create a 2-byte string from a UTF-8 encoded string literal.
1487 {
1488 const char* src =
1489 "\xD7\x92\xD7\x9C\xD7\xA2\xD7\x93"
1490 "\xD7\x91\xD7\xA8\xD7\x9B\xD7\x94";
1491 const uint16_t expected[] = {0x5D2, 0x5DC, 0x5E2, 0x5D3,
1492 0x5D1, 0x5E8, 0x5DB, 0x5D4};
1493 const String& str = String::Handle(String::New(src));
1494 EXPECT(str.IsTwoByteString());
1495 intptr_t expected_size = sizeof(expected) / sizeof(expected[0]);
1496 EXPECT_EQ(expected_size, str.Length());
1497 for (int i = 0; i < str.Length(); ++i) {
1498 EXPECT_EQ(expected[i], str.CharAt(i));
1499 }
1500 }
1501
1502 // Create a BMP 2-byte string from UTF-8 encoded 1- and 2-byte
1503 // characters.
1504 {
1505 const char* src =
1506 "\x0A\x0B\x0D\x0C\x0E\x0F\xC2\xA0"
1507 "\xC2\xB0\xC3\x80\xC3\x90\xC3\xA0"
1508 "\xC3\xB0\xE0\xA8\x80\xE0\xAC\x80"
1509 "\xE0\xB0\x80\xE0\xB4\x80\xE0\xB8"
1510 "\x80\xE0\xBC\x80\xEA\x80\x80\xEB"
1511 "\x80\x80\xEC\x80\x80\xED\x80\x80"
1512 "\xEE\x80\x80\xEF\x80\x80";
1513 const intptr_t expected[] = {
1514 0x000A, 0x000B, 0x000D, 0x000C, 0x000E, 0x000F, 0x00A0, 0x00B0,
1515 0x00C0, 0x00D0, 0x00E0, 0x00F0, 0x0A00, 0x0B00, 0x0C00, 0x0D00,
1516 0x0E00, 0x0F00, 0xA000, 0xB000, 0xC000, 0xD000, 0xE000, 0xF000};
1517 const String& str = String::Handle(String::New(src));
1518 EXPECT(str.IsTwoByteString());
1519 intptr_t expected_size = sizeof(expected) / sizeof(expected[0]);
1520 EXPECT_EQ(expected_size, str.Length());
1521 for (int i = 0; i < str.Length(); ++i) {
1522 EXPECT_EQ(expected[i], str.CharAt(i));
1523 }
1524 }
1525
1526 // Create a 2-byte string with supplementary characters from a UTF-8
1527 // string literal.
1528 {
1529 const char* src =
1530 "\xF0\x9D\x91\xA0\xF0\x9D\x91\xA1"
1531 "\xF0\x9D\x91\xA2\xF0\x9D\x91\xA3";
1532 const intptr_t expected[] = {0xd835, 0xdc60, 0xd835, 0xdc61,
1533 0xd835, 0xdc62, 0xd835, 0xdc63};
1534 const String& str = String::Handle(String::New(src));
1535 EXPECT(str.IsTwoByteString());
1536 intptr_t expected_size = (sizeof(expected) / sizeof(expected[0]));
1537 EXPECT_EQ(expected_size, str.Length());
1538 for (int i = 0; i < str.Length(); ++i) {
1539 EXPECT_EQ(expected[i], str.CharAt(i));
1540 }
1541 }
1542
1543 // Create a 2-byte string from UTF-8 encoded 2- and 4-byte
1544 // characters.
1545 {
1546 const char* src =
1547 "\xE0\xA8\x80\xE0\xAC\x80\xE0\xB0"
1548 "\x80\xE0\xB4\x80\xE0\xB8\x80\xE0"
1549 "\xBC\x80\xEA\x80\x80\xEB\x80\x80"
1550 "\xEC\x80\x80\xED\x80\x80\xEE\x80"
1551 "\x80\xEF\x80\x80\xF0\x9A\x80\x80"
1552 "\xF0\x9B\x80\x80\xF0\x9D\x80\x80"
1553 "\xF0\x9E\x80\x80\xF0\x9F\x80\x80";
1554 const intptr_t expected[] = {
1555 0x0A00, 0x0B00, 0x0C00, 0x0D00, 0x0E00, 0x0F00, 0xA000, 0xB000,
1556 0xC000, 0xD000, 0xE000, 0xF000, 0xD828, 0xDC00, 0xD82c, 0xDC00,
1557 0xD834, 0xDC00, 0xD838, 0xDC00, 0xD83c, 0xDC00,
1558 };
1559 const String& str = String::Handle(String::New(src));
1560 EXPECT(str.IsTwoByteString());
1561 intptr_t expected_size = sizeof(expected) / sizeof(expected[0]);
1562 EXPECT_EQ(expected_size, str.Length());
1563 for (int i = 0; i < str.Length(); ++i) {
1564 EXPECT_EQ(expected[i], str.CharAt(i));
1565 }
1566 }
1567
1568 // Create a 2-byte string from UTF-8 encoded 1-, 2- and 4-byte
1569 // characters.
1570 {
1571 const char* src =
1572 "\x0A\x0B\x0D\x0C\x0E\x0F\xC2\xA0"
1573 "\xC2\xB0\xC3\x80\xC3\x90\xC3\xA0"
1574 "\xC3\xB0\xE0\xA8\x80\xE0\xAC\x80"
1575 "\xE0\xB0\x80\xE0\xB4\x80\xE0\xB8"
1576 "\x80\xE0\xBC\x80\xEA\x80\x80\xEB"
1577 "\x80\x80\xEC\x80\x80\xED\x80\x80"
1578 "\xEE\x80\x80\xEF\x80\x80\xF0\x9A"
1579 "\x80\x80\xF0\x9B\x80\x80\xF0\x9D"
1580 "\x80\x80\xF0\x9E\x80\x80\xF0\x9F"
1581 "\x80\x80";
1582 const intptr_t expected[] = {
1583 0x000A, 0x000B, 0x000D, 0x000C, 0x000E, 0x000F, 0x00A0, 0x00B0, 0x00C0,
1584 0x00D0, 0x00E0, 0x00F0, 0x0A00, 0x0B00, 0x0C00, 0x0D00, 0x0E00, 0x0F00,
1585 0xA000, 0xB000, 0xC000, 0xD000, 0xE000, 0xF000, 0xD828, 0xDC00, 0xD82c,
1586 0xDC00, 0xD834, 0xDC00, 0xD838, 0xDC00, 0xD83c, 0xDC00,
1587 };
1588 const String& str = String::Handle(String::New(src));
1589 EXPECT(str.IsTwoByteString());
1590 intptr_t expected_size = sizeof(expected) / sizeof(expected[0]);
1591 EXPECT_EQ(expected_size, str.Length());
1592 for (int i = 0; i < str.Length(); ++i) {
1593 EXPECT_EQ(expected[i], str.CharAt(i));
1594 }
1595 }
1596}
1597
1598ISOLATE_UNIT_TEST_CASE(StringEqualsUtf8) {
1599 const char* onesrc = "abc";
1600 const String& onestr = String::Handle(String::New(onesrc));
1601 EXPECT(onestr.IsOneByteString());
1602 EXPECT(!onestr.Equals(""));
1603 EXPECT(!onestr.Equals("a"));
1604 EXPECT(!onestr.Equals("ab"));
1605 EXPECT(onestr.Equals("abc"));
1606 EXPECT(!onestr.Equals("abcd"));
1607
1608 const char* twosrc = "\xD7\x90\xD7\x91\xD7\x92";
1609 const String& twostr = String::Handle(String::New(twosrc));
1610 EXPECT(twostr.IsTwoByteString());
1611 EXPECT(!twostr.Equals(""));
1612 EXPECT(!twostr.Equals("\xD7\x90"));
1613 EXPECT(!twostr.Equals("\xD7\x90\xD7\x91"));
1614 EXPECT(twostr.Equals("\xD7\x90\xD7\x91\xD7\x92"));
1615 EXPECT(!twostr.Equals("\xD7\x90\xD7\x91\xD7\x92\xD7\x93"));
1616
1617 const char* foursrc = "\xF0\x90\x8E\xA0\xF0\x90\x8E\xA1\xF0\x90\x8E\xA2";
1618 const String& fourstr = String::Handle(String::New(foursrc));
1619 EXPECT(fourstr.IsTwoByteString());
1620 EXPECT(!fourstr.Equals(""));
1621 EXPECT(!fourstr.Equals("\xF0\x90\x8E\xA0"));
1622 EXPECT(!fourstr.Equals("\xF0\x90\x8E\xA0\xF0\x90\x8E\xA1"));
1623 EXPECT(fourstr.Equals("\xF0\x90\x8E\xA0\xF0\x90\x8E\xA1\xF0\x90\x8E\xA2"));
1624 EXPECT(
1625 !fourstr.Equals("\xF0\x90\x8E\xA0\xF0\x90\x8E\xA1"
1626 "\xF0\x90\x8E\xA2\xF0\x90\x8E\xA3"));
1627}
1628
1629ISOLATE_UNIT_TEST_CASE(StringEqualsUTF32) {
1630 const String& empty = String::Handle(String::New(""));
1631 const String& t_str = String::Handle(String::New("t"));
1632 const String& th_str = String::Handle(String::New("th"));
1633 const int32_t chars[] = {'t', 'h', 'i', 's'};
1634 EXPECT(!empty.Equals(chars, -1));
1635 EXPECT(empty.Equals(chars, 0));
1636 EXPECT(!empty.Equals(chars, 1));
1637 EXPECT(!t_str.Equals(chars, 0));
1638 EXPECT(t_str.Equals(chars, 1));
1639 EXPECT(!t_str.Equals(chars, 2));
1640 EXPECT(!th_str.Equals(chars, 1));
1641 EXPECT(th_str.Equals(chars, 2));
1642 EXPECT(!th_str.Equals(chars, 3));
1643}
1644
1645ISOLATE_UNIT_TEST_CASE(EscapeSpecialCharactersOneByteString) {
1646 uint8_t characters[] = {'a', '\n', '\f', '\b', '\t',
1647 '\v', '\r', '\\', '$', 'z'};
1648 intptr_t len = ARRAY_SIZE(characters);
1649
1650 const String& str =
1652 EXPECT(str.IsOneByteString());
1653 EXPECT_EQ(str.Length(), len);
1654 EXPECT(str.Equals("a\n\f\b\t\v\r\\$z"));
1655 const String& escaped_str =
1657 EXPECT(escaped_str.Equals("a\\n\\f\\b\\t\\v\\r\\\\\\$z"));
1658
1659 const String& escaped_empty_str =
1661 EXPECT_EQ(escaped_empty_str.Length(), 0);
1662}
1663
1664ISOLATE_UNIT_TEST_CASE(EscapeSpecialCharactersTwoByteString) {
1665 uint16_t characters[] = {'a', '\n', '\f', '\b', '\t',
1666 '\v', '\r', '\\', '$', 'z'};
1667 intptr_t len = ARRAY_SIZE(characters);
1668
1669 const String& str =
1671 EXPECT(str.IsTwoByteString());
1672 EXPECT_EQ(str.Length(), len);
1673 EXPECT(str.Equals("a\n\f\b\t\v\r\\$z"));
1674 const String& escaped_str =
1676 EXPECT(escaped_str.Equals("a\\n\\f\\b\\t\\v\\r\\\\\\$z"));
1677
1678 const String& empty_str =
1679 String::Handle(TwoByteString::New(static_cast<intptr_t>(0), Heap::kNew));
1680 const String& escaped_empty_str =
1682 EXPECT_EQ(empty_str.Length(), 0);
1683 EXPECT_EQ(escaped_empty_str.Length(), 0);
1684}
1685
1687 const String& one = String::Handle(Symbols::New(thread, "Eins"));
1688 EXPECT(one.IsSymbol());
1689 const String& two = String::Handle(Symbols::New(thread, "Zwei"));
1690 const String& three = String::Handle(Symbols::New(thread, "Drei"));
1691 const String& four = String::Handle(Symbols::New(thread, "Vier"));
1692 const String& five = String::Handle(Symbols::New(thread, "Fuenf"));
1693 const String& six = String::Handle(Symbols::New(thread, "Sechs"));
1694 const String& seven = String::Handle(Symbols::New(thread, "Sieben"));
1695 const String& eight = String::Handle(Symbols::New(thread, "Acht"));
1696 const String& nine = String::Handle(Symbols::New(thread, "Neun"));
1697 const String& ten = String::Handle(Symbols::New(thread, "Zehn"));
1698 String& eins = String::Handle(Symbols::New(thread, "Eins"));
1699 EXPECT_EQ(one.ptr(), eins.ptr());
1700 EXPECT(one.ptr() != two.ptr());
1701 EXPECT(two.Equals(String::Handle(String::New("Zwei"))));
1702 EXPECT_EQ(two.ptr(), Symbols::New(thread, "Zwei"));
1703 EXPECT_EQ(three.ptr(), Symbols::New(thread, "Drei"));
1704 EXPECT_EQ(four.ptr(), Symbols::New(thread, "Vier"));
1705 EXPECT_EQ(five.ptr(), Symbols::New(thread, "Fuenf"));
1706 EXPECT_EQ(six.ptr(), Symbols::New(thread, "Sechs"));
1707 EXPECT_EQ(seven.ptr(), Symbols::New(thread, "Sieben"));
1708 EXPECT_EQ(eight.ptr(), Symbols::New(thread, "Acht"));
1709 EXPECT_EQ(nine.ptr(), Symbols::New(thread, "Neun"));
1710 EXPECT_EQ(ten.ptr(), Symbols::New(thread, "Zehn"));
1711
1712 // Make sure to cause symbol table overflow.
1713 for (int i = 0; i < 1024; i++) {
1714 char buf[256];
1715 Utils::SNPrint(buf, sizeof(buf), "%d", i);
1716 Symbols::New(thread, buf);
1717 }
1718 eins = Symbols::New(thread, "Eins");
1719 EXPECT_EQ(one.ptr(), eins.ptr());
1720 EXPECT_EQ(two.ptr(), Symbols::New(thread, "Zwei"));
1721 EXPECT_EQ(three.ptr(), Symbols::New(thread, "Drei"));
1722 EXPECT_EQ(four.ptr(), Symbols::New(thread, "Vier"));
1723 EXPECT_EQ(five.ptr(), Symbols::New(thread, "Fuenf"));
1724 EXPECT_EQ(six.ptr(), Symbols::New(thread, "Sechs"));
1725 EXPECT_EQ(seven.ptr(), Symbols::New(thread, "Sieben"));
1726 EXPECT_EQ(eight.ptr(), Symbols::New(thread, "Acht"));
1727 EXPECT_EQ(nine.ptr(), Symbols::New(thread, "Neun"));
1728 EXPECT_EQ(ten.ptr(), Symbols::New(thread, "Zehn"));
1729
1730 // Symbols from Strings.
1731 eins = String::New("Eins");
1732 EXPECT(!eins.IsSymbol());
1733 String& ein_symbol = String::Handle(Symbols::New(thread, eins));
1734 EXPECT_EQ(one.ptr(), ein_symbol.ptr());
1735 EXPECT(one.ptr() != eins.ptr());
1736
1737 uint16_t char16[] = {'E', 'l', 'f'};
1738 String& elf1 = String::Handle(Symbols::FromUTF16(thread, char16, 3));
1739 int32_t char32[] = {'E', 'l', 'f'};
1740 String& elf2 = String::Handle(
1741 Symbols::New(thread, String::Handle(String::FromUTF32(char32, 3))));
1742 EXPECT(elf1.IsSymbol());
1743 EXPECT(elf2.IsSymbol());
1744 EXPECT_EQ(elf1.ptr(), Symbols::New(thread, "Elf"));
1745 EXPECT_EQ(elf2.ptr(), Symbols::New(thread, "Elf"));
1746}
1747
1749 uint16_t monkey_utf16[] = {0xd83d, 0xdc35}; // Unicode Monkey Face.
1750 String& monkey = String::Handle(Symbols::FromUTF16(thread, monkey_utf16, 2));
1751 EXPECT(monkey.IsSymbol());
1752 const char monkey_utf8[] = {'\xf0', '\x9f', '\x90', '\xb5', 0};
1753 EXPECT_EQ(monkey.ptr(), Symbols::New(thread, monkey_utf8));
1754
1755 int32_t kMonkeyFace = 0x1f435;
1756 String& monkey2 = String::Handle(
1757 Symbols::New(thread, String::Handle(String::FromUTF32(&kMonkeyFace, 1))));
1758 EXPECT_EQ(monkey.ptr(), monkey2.ptr());
1759
1760 // Unicode cat face with tears of joy.
1761 int32_t kCatFaceWithTearsOfJoy = 0x1f639;
1763 thread, String::Handle(String::FromUTF32(&kCatFaceWithTearsOfJoy, 1))));
1764
1765 uint16_t cat_utf16[] = {0xd83d, 0xde39};
1766 String& cat2 = String::Handle(Symbols::FromUTF16(thread, cat_utf16, 2));
1767 EXPECT(cat2.IsSymbol());
1768 EXPECT_EQ(cat2.ptr(), cat.ptr());
1769}
1770
1772 EXPECT(Bool::True().value());
1773 EXPECT(!Bool::False().value());
1774}
1775
1777 const int kArrayLen = 5;
1778 const Array& array = Array::Handle(Array::New(kArrayLen));
1779 EXPECT_EQ(kArrayLen, array.Length());
1780 Object& element = Object::Handle(array.At(0));
1781 EXPECT(element.IsNull());
1782 element = array.At(kArrayLen - 1);
1783 EXPECT(element.IsNull());
1784 array.SetAt(0, array);
1785 array.SetAt(2, array);
1786 element = array.At(0);
1787 EXPECT_EQ(array.ptr(), element.ptr());
1788 element = array.At(1);
1789 EXPECT(element.IsNull());
1790 element = array.At(2);
1791 EXPECT_EQ(array.ptr(), element.ptr());
1792
1793 Array& other_array = Array::Handle(Array::New(kArrayLen));
1794 other_array.SetAt(0, array);
1795 other_array.SetAt(2, array);
1796
1797 EXPECT(array.CanonicalizeEquals(array));
1798 EXPECT(array.CanonicalizeEquals(other_array));
1799
1800 other_array.SetAt(1, other_array);
1801 EXPECT(!array.CanonicalizeEquals(other_array));
1802
1803 other_array = Array::New(kArrayLen - 1);
1804 other_array.SetAt(0, array);
1805 other_array.SetAt(2, array);
1806 EXPECT(!array.CanonicalizeEquals(other_array));
1807
1808 EXPECT_EQ(0, Object::empty_array().Length());
1809
1810 array.MakeImmutable();
1811 Object& obj = Object::Handle(array.ptr());
1812 EXPECT(obj.IsArray());
1813}
1814
1816 const intptr_t kSmallSize = 100;
1818 const intptr_t kMediumSize = 1000;
1820 const intptr_t kLargeSize = 100000;
1822
1823 const Array& small = Array::Handle(Array::New(kSmallSize));
1824 for (intptr_t i = 0; i < kSmallSize; i++) {
1825 small.SetAt(i, Smi::Handle(Smi::New(i)));
1826 }
1827
1828 const Array& medium = Array::Handle(Array::Grow(small, kMediumSize));
1829 EXPECT_EQ(kMediumSize, medium.Length());
1830 for (intptr_t i = 0; i < kSmallSize; i++) {
1831 EXPECT_EQ(Smi::New(i), medium.At(i));
1832 }
1833 for (intptr_t i = kSmallSize; i < kMediumSize; i++) {
1834 EXPECT_EQ(Object::null(), medium.At(i));
1835 }
1836
1837 const Array& large = Array::Handle(Array::Grow(small, kLargeSize));
1838 EXPECT_EQ(kLargeSize, large.Length());
1839 for (intptr_t i = 0; i < kSmallSize; i++) {
1840 EXPECT_EQ(large.At(i), Smi::New(i));
1841 }
1842 for (intptr_t i = kSmallSize; i < kLargeSize; i++) {
1843 EXPECT_EQ(large.At(i), Object::null());
1844 }
1845}
1846
1847ISOLATE_UNIT_TEST_CASE(EmptyInstantiationsCacheArray) {
1849 thread->isolate_group()->type_arguments_canonicalization_mutex());
1850 const Array& empty_cache = Object::empty_instantiations_cache_array();
1851 DEBUG_ONLY(EXPECT(TypeArguments::Cache::IsValidStorageLocked(empty_cache));)
1852 const TypeArguments::Cache cache(thread->zone(), empty_cache);
1853 EXPECT(cache.IsLinear());
1854 EXPECT(!cache.IsHash());
1855 EXPECT_EQ(0, cache.NumOccupied());
1856 const InstantiationsCacheTable table(empty_cache);
1857 EXPECT_EQ(1, table.Length());
1858 for (const auto& tuple : table) {
1861 }
1862}
1863
1864static void TestIllegalArrayLength(intptr_t length) {
1865 char buffer[1024];
1866 Utils::SNPrint(buffer, sizeof(buffer),
1867 "main() {\n"
1868 " List.filled(%" Pd
1869 ", null);\n"
1870 "}\n",
1871 length);
1873 EXPECT_VALID(lib);
1874 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, nullptr);
1875 Utils::SNPrint(buffer, sizeof(buffer),
1876 "Unhandled exception:\n"
1877 "RangeError (length): Invalid value: "
1878 "Not in inclusive range 0..%" Pd ": %" Pd,
1881}
1882
1883TEST_CASE(ArrayLengthNegativeOne) {
1885}
1886TEST_CASE(ArrayLengthSmiMin) {
1888}
1889
1890TEST_CASE(ArrayLengthOneTooMany) {
1891 const intptr_t kOneTooMany = Array::kMaxElements + 1;
1892 ASSERT(kOneTooMany >= 0);
1893
1894 char buffer[1024];
1895 Utils::SNPrint(buffer, sizeof(buffer),
1896 "main() {\n"
1897 " return List.filled(%" Pd
1898 ", null);\n"
1899 "}\n",
1900 kOneTooMany);
1902 EXPECT_VALID(lib);
1903 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, nullptr);
1904 EXPECT_ERROR(result, "Out of Memory");
1905}
1906
1907TEST_CASE(ArrayLengthMaxElements) {
1908 char buffer[1024];
1909 Utils::SNPrint(buffer, sizeof(buffer),
1910 "main() {\n"
1911 " return List.filled(%" Pd
1912 ", null);\n"
1913 "}\n",
1916 EXPECT_VALID(lib);
1917 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, nullptr);
1918 if (Dart_IsError(result)) {
1919 EXPECT_ERROR(result, "Out of Memory");
1920 } else {
1921 const intptr_t kExpected = Array::kMaxElements;
1922 intptr_t actual = 0;
1924 EXPECT_EQ(kExpected, actual);
1925 }
1926}
1927
1929 intptr_t length) {
1930 char buffer[1024];
1931 Utils::SNPrint(buffer, sizeof(buffer),
1932 "import 'dart:typed_data';\n"
1933 "main() {\n"
1934 " new %s(%" Pd
1935 ");\n"
1936 "}\n",
1939 EXPECT_VALID(lib);
1940 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, nullptr);
1941 Utils::SNPrint(buffer, sizeof(buffer), "%" Pd, length);
1942 EXPECT_ERROR(result, "RangeError (length): Invalid value");
1944}
1945
1946TEST_CASE(Int8ListLengthNegativeOne) {
1947 TestIllegalTypedDataLength("Int8List", -1);
1948}
1949TEST_CASE(Int8ListLengthSmiMin) {
1951}
1952TEST_CASE(Int8ListLengthOneTooMany) {
1953 const intptr_t kOneTooMany =
1954 TypedData::MaxElements(kTypedDataInt8ArrayCid) + 1;
1955 ASSERT(kOneTooMany >= 0);
1956
1957 char buffer[1024];
1958 Utils::SNPrint(buffer, sizeof(buffer),
1959 "import 'dart:typed_data';\n"
1960 "main() {\n"
1961 " return new Int8List(%" Pd
1962 ");\n"
1963 "}\n",
1964 kOneTooMany);
1966 EXPECT_VALID(lib);
1967 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, nullptr);
1968 EXPECT_ERROR(result, "Out of Memory");
1969}
1970
1971TEST_CASE(Int8ListLengthMaxElements) {
1972 const intptr_t max_elements = TypedData::MaxElements(kTypedDataInt8ArrayCid);
1973 char buffer[1024];
1974 Utils::SNPrint(buffer, sizeof(buffer),
1975 "import 'dart:typed_data';\n"
1976 "main() {\n"
1977 " return new Int8List(%" Pd
1978 ");\n"
1979 "}\n",
1980 max_elements);
1982 EXPECT_VALID(lib);
1983 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, nullptr);
1984 if (Dart_IsError(result)) {
1985 EXPECT_ERROR(result, "Out of Memory");
1986 } else {
1987 intptr_t actual = 0;
1989 EXPECT_EQ(max_elements, actual);
1990 }
1991}
1992
1993ISOLATE_UNIT_TEST_CASE(StringCodePointIterator) {
1994 const String& str0 = String::Handle(String::New(""));
1995 String::CodePointIterator it0(str0);
1996 EXPECT(!it0.Next());
1997
1998 const String& str1 = String::Handle(String::New(" \xc3\xa7 "));
1999 String::CodePointIterator it1(str1);
2000 EXPECT(it1.Next());
2001 EXPECT_EQ(' ', it1.Current());
2002 EXPECT(it1.Next());
2003 EXPECT_EQ(0xE7, it1.Current());
2004 EXPECT(it1.Next());
2005 EXPECT_EQ(' ', it1.Current());
2006 EXPECT(!it1.Next());
2007
2008 const String& str2 =
2009 String::Handle(String::New("\xD7\x92\xD7\x9C"
2010 "\xD7\xA2\xD7\x93"
2011 "\xD7\x91\xD7\xA8"
2012 "\xD7\x9B\xD7\x94"));
2013 String::CodePointIterator it2(str2);
2014 EXPECT(it2.Next());
2015 EXPECT_EQ(0x5D2, it2.Current());
2016 EXPECT(it2.Next());
2017 EXPECT_EQ(0x5DC, it2.Current());
2018 EXPECT(it2.Next());
2019 EXPECT_EQ(0x5E2, it2.Current());
2020 EXPECT(it2.Next());
2021 EXPECT_EQ(0x5D3, it2.Current());
2022 EXPECT(it2.Next());
2023 EXPECT_EQ(0x5D1, it2.Current());
2024 EXPECT(it2.Next());
2025 EXPECT_EQ(0x5E8, it2.Current());
2026 EXPECT(it2.Next());
2027 EXPECT_EQ(0x5DB, it2.Current());
2028 EXPECT(it2.Next());
2029 EXPECT_EQ(0x5D4, it2.Current());
2030 EXPECT(!it2.Next());
2031
2032 const String& str3 =
2033 String::Handle(String::New("\xF0\x9D\x91\xA0"
2034 "\xF0\x9D\x91\xA1"
2035 "\xF0\x9D\x91\xA2"
2036 "\xF0\x9D\x91\xA3"));
2037 String::CodePointIterator it3(str3);
2038 EXPECT(it3.Next());
2039 EXPECT_EQ(0x1D460, it3.Current());
2040 EXPECT(it3.Next());
2041 EXPECT_EQ(0x1D461, it3.Current());
2042 EXPECT(it3.Next());
2043 EXPECT_EQ(0x1D462, it3.Current());
2044 EXPECT(it3.Next());
2045 EXPECT_EQ(0x1D463, it3.Current());
2046 EXPECT(!it3.Next());
2047}
2048
2049ISOLATE_UNIT_TEST_CASE(StringCodePointIteratorRange) {
2050 const String& str = String::Handle(String::New("foo bar baz"));
2051
2052 String::CodePointIterator it0(str, 3, 0);
2053 EXPECT(!it0.Next());
2054
2055 String::CodePointIterator it1(str, 4, 3);
2056 EXPECT(it1.Next());
2057 EXPECT_EQ('b', it1.Current());
2058 EXPECT(it1.Next());
2059 EXPECT_EQ('a', it1.Current());
2060 EXPECT(it1.Next());
2061 EXPECT_EQ('r', it1.Current());
2062 EXPECT(!it1.Next());
2063}
2064
2066 const int kArrayLen = 5;
2067 Smi& value = Smi::Handle();
2070
2071 // Test basic growing functionality.
2072 array = GrowableObjectArray::New(kArrayLen);
2073 EXPECT_EQ(kArrayLen, array.Capacity());
2074 EXPECT_EQ(0, array.Length());
2075 for (intptr_t i = 0; i < 10; i++) {
2076 value = Smi::New(i);
2077 array.Add(value);
2078 }
2079 EXPECT_EQ(10, array.Length());
2080 for (intptr_t i = 0; i < 10; i++) {
2082 value ^= array.At(i);
2083 EXPECT(value.Equals(expected_value));
2084 }
2085 for (intptr_t i = 0; i < 10; i++) {
2086 value = Smi::New(i * 10);
2087 array.SetAt(i, value);
2088 }
2089 EXPECT_EQ(10, array.Length());
2090 for (intptr_t i = 0; i < 10; i++) {
2091 expected_value = Smi::New(i * 10);
2092 value ^= array.At(i);
2093 EXPECT(value.Equals(expected_value));
2094 }
2095
2096 // Test the MakeFixedLength functionality to make sure the resulting array
2097 // object is properly setup.
2098 // 1. Should produce an array of length 2 and a filler of minimal size.
2099 Array& new_array = Array::Handle();
2100 Object& obj = Object::Handle();
2101 uword addr = 0;
2102 intptr_t used_size = 0;
2103
2104 array = GrowableObjectArray::New(kArrayLen + 1);
2105 EXPECT_EQ(kArrayLen + 1, array.Capacity());
2106 EXPECT_EQ(0, array.Length());
2107 for (intptr_t i = 0; i < 2; i++) {
2108 value = Smi::New(i);
2109 array.Add(value);
2110 }
2111 used_size = Array::InstanceSize(array.Length());
2112 new_array = Array::MakeFixedLength(array);
2113 addr = UntaggedObject::ToAddr(new_array.ptr());
2115 EXPECT(obj.IsArray());
2116 new_array ^= obj.ptr();
2117 EXPECT_EQ(2, new_array.Length());
2118 addr += used_size;
2120 EXPECT(filler->IsFreeListElement());
2121 EXPECT_EQ(filler->untag()->HeapSize(),
2122 Array::InstanceSize(kArrayLen + 1) - used_size);
2123
2124 // 2. Should produce an array of length 3 and a filler object.
2125 array = GrowableObjectArray::New(kArrayLen);
2126 EXPECT_EQ(kArrayLen, array.Capacity());
2127 EXPECT_EQ(0, array.Length());
2128 for (intptr_t i = 0; i < 3; i++) {
2129 value = Smi::New(i);
2130 array.Add(value);
2131 }
2132 used_size = Array::InstanceSize(array.Length());
2133 new_array = Array::MakeFixedLength(array);
2134 addr = UntaggedObject::ToAddr(new_array.ptr());
2136 EXPECT(obj.IsArray());
2137 new_array ^= obj.ptr();
2138 EXPECT_EQ(3, new_array.Length());
2139 addr += used_size;
2141 EXPECT(filler->IsFreeListElement());
2142 EXPECT_EQ(filler->untag()->HeapSize(),
2143 Array::InstanceSize(kArrayLen) - used_size);
2144
2145 // 3. Should produce an array of length 1 and a filler object.
2146 array = GrowableObjectArray::New(kArrayLen + 3);
2147 EXPECT_EQ((kArrayLen + 3), array.Capacity());
2148 EXPECT_EQ(0, array.Length());
2149 for (intptr_t i = 0; i < 1; i++) {
2150 value = Smi::New(i);
2151 array.Add(value);
2152 }
2153 used_size = Array::InstanceSize(array.Length());
2154 new_array = Array::MakeFixedLength(array);
2155 addr = UntaggedObject::ToAddr(new_array.ptr());
2157 EXPECT(obj.IsArray());
2158 new_array ^= obj.ptr();
2159 EXPECT_EQ(1, new_array.Length());
2160 addr += used_size;
2162 EXPECT(filler->IsFreeListElement());
2163 EXPECT_EQ(filler->untag()->HeapSize(),
2164 Array::InstanceSize(kArrayLen + 3) - used_size);
2165
2166 // 4. Verify that GC can handle the filler object for a large array.
2167 array = GrowableObjectArray::New((1 * MB) >> kWordSizeLog2);
2168 EXPECT_EQ(0, array.Length());
2169 for (intptr_t i = 0; i < 1; i++) {
2170 value = Smi::New(i);
2171 array.Add(value);
2172 }
2173 Heap* heap = IsolateGroup::Current()->heap();
2175 GCTestHelper::WaitForGCTasks(); // Sweeper must finish for accurate capacity.
2176 intptr_t capacity_before = heap->CapacityInWords(Heap::kOld);
2177 new_array = Array::MakeFixedLength(array);
2178 EXPECT_EQ(1, new_array.Length());
2180 GCTestHelper::WaitForGCTasks(); // Sweeper must finish for accurate capacity.
2181 intptr_t capacity_after = heap->CapacityInWords(Heap::kOld);
2182 // Page should shrink.
2183 EXPECT_LT(capacity_after, capacity_before);
2184 EXPECT_EQ(1, new_array.Length());
2185}
2186
2187ISOLATE_UNIT_TEST_CASE(TypedData_Grow) {
2188 const intptr_t kSmallSize = 42;
2189 const intptr_t kLargeSize = 1000;
2190
2191 Random random(42);
2192
2196
2197 const auto& small = TypedData::Handle(TypedData::New(cid, kSmallSize));
2198 EXPECT_EQ(small.LengthInBytes(), kSmallSize * small.ElementSizeInBytes());
2199
2200 for (intptr_t i = 0; i < TypedData::ElementSizeFor(cid) * kSmallSize; i++) {
2201 small.SetUint8(i, static_cast<uint8_t>(random.NextUInt64() & 0xff));
2202 }
2203
2204 const auto& big = TypedData::Handle(TypedData::Grow(small, kLargeSize));
2205 EXPECT_EQ(small.GetClassId(), big.GetClassId());
2206 EXPECT_EQ(big.LengthInBytes(), kLargeSize * big.ElementSizeInBytes());
2207
2208 for (intptr_t i = 0; i < TypedData::ElementSizeFor(cid) * kSmallSize; i++) {
2209 EXPECT_EQ(small.GetUint8(i), big.GetUint8(i));
2210 }
2211 for (intptr_t i = TypedData::ElementSizeFor(cid) * kSmallSize;
2212 i < TypedData::ElementSizeFor(cid) * kLargeSize; i++) {
2213 EXPECT_EQ(0, big.GetUint8(i));
2214 }
2215 }
2216}
2217
2218ISOLATE_UNIT_TEST_CASE(InternalTypedData) {
2219 uint8_t data[] = {253, 254, 255, 0, 1, 2, 3, 4};
2220 intptr_t data_length = ARRAY_SIZE(data);
2221
2222 const TypedData& int8_array =
2223 TypedData::Handle(TypedData::New(kTypedDataInt8ArrayCid, data_length));
2224 EXPECT(!int8_array.IsNull());
2225 EXPECT_EQ(data_length, int8_array.Length());
2226 for (intptr_t i = 0; i < data_length; ++i) {
2227 int8_array.SetInt8(i, data[i]);
2228 }
2229
2230 EXPECT_EQ(-3, int8_array.GetInt8(0));
2231 EXPECT_EQ(253, int8_array.GetUint8(0));
2232
2233 EXPECT_EQ(-2, int8_array.GetInt8(1));
2234 EXPECT_EQ(254, int8_array.GetUint8(1));
2235
2236 EXPECT_EQ(-1, int8_array.GetInt8(2));
2237 EXPECT_EQ(255, int8_array.GetUint8(2));
2238
2239 EXPECT_EQ(0, int8_array.GetInt8(3));
2240 EXPECT_EQ(0, int8_array.GetUint8(3));
2241
2242 EXPECT_EQ(1, int8_array.GetInt8(4));
2243 EXPECT_EQ(1, int8_array.GetUint8(4));
2244
2245 EXPECT_EQ(2, int8_array.GetInt8(5));
2246 EXPECT_EQ(2, int8_array.GetUint8(5));
2247
2248 EXPECT_EQ(3, int8_array.GetInt8(6));
2249 EXPECT_EQ(3, int8_array.GetUint8(6));
2250
2251 EXPECT_EQ(4, int8_array.GetInt8(7));
2252 EXPECT_EQ(4, int8_array.GetUint8(7));
2253
2254 const TypedData& int8_array2 =
2255 TypedData::Handle(TypedData::New(kTypedDataInt8ArrayCid, data_length));
2256 EXPECT(!int8_array.IsNull());
2257 EXPECT_EQ(data_length, int8_array.Length());
2258 for (intptr_t i = 0; i < data_length; ++i) {
2259 int8_array2.SetInt8(i, data[i]);
2260 }
2261
2262 for (intptr_t i = 0; i < data_length; ++i) {
2263 EXPECT_EQ(int8_array.GetInt8(i), int8_array2.GetInt8(i));
2264 }
2265 for (intptr_t i = 0; i < data_length; ++i) {
2266 int8_array.SetInt8(i, 123 + i);
2267 }
2268 for (intptr_t i = 0; i < data_length; ++i) {
2269 EXPECT(int8_array.GetInt8(i) != int8_array2.GetInt8(i));
2270 }
2271}
2272
2274 uint8_t data[] = {253, 254, 255, 0, 1, 2, 3, 4};
2275 intptr_t data_length = ARRAY_SIZE(data);
2276
2277 const ExternalTypedData& int8_array =
2279 kExternalTypedDataInt8ArrayCid, data, data_length));
2280 EXPECT(!int8_array.IsNull());
2281 EXPECT_EQ(data_length, int8_array.Length());
2282
2283 const ExternalTypedData& uint8_array =
2285 kExternalTypedDataUint8ArrayCid, data, data_length));
2286 EXPECT(!uint8_array.IsNull());
2287 EXPECT_EQ(data_length, uint8_array.Length());
2288
2289 const ExternalTypedData& uint8_clamped_array =
2291 kExternalTypedDataUint8ClampedArrayCid, data, data_length));
2292 EXPECT(!uint8_clamped_array.IsNull());
2293 EXPECT_EQ(data_length, uint8_clamped_array.Length());
2294
2295 EXPECT_EQ(-3, int8_array.GetInt8(0));
2296 EXPECT_EQ(253, uint8_array.GetUint8(0));
2297 EXPECT_EQ(253, uint8_clamped_array.GetUint8(0));
2298
2299 EXPECT_EQ(-2, int8_array.GetInt8(1));
2300 EXPECT_EQ(254, uint8_array.GetUint8(1));
2301 EXPECT_EQ(254, uint8_clamped_array.GetUint8(1));
2302
2303 EXPECT_EQ(-1, int8_array.GetInt8(2));
2304 EXPECT_EQ(255, uint8_array.GetUint8(2));
2305 EXPECT_EQ(255, uint8_clamped_array.GetUint8(2));
2306
2307 EXPECT_EQ(0, int8_array.GetInt8(3));
2308 EXPECT_EQ(0, uint8_array.GetUint8(3));
2309 EXPECT_EQ(0, uint8_clamped_array.GetUint8(3));
2310
2311 EXPECT_EQ(1, int8_array.GetInt8(4));
2312 EXPECT_EQ(1, uint8_array.GetUint8(4));
2313 EXPECT_EQ(1, uint8_clamped_array.GetUint8(4));
2314
2315 EXPECT_EQ(2, int8_array.GetInt8(5));
2316 EXPECT_EQ(2, uint8_array.GetUint8(5));
2317 EXPECT_EQ(2, uint8_clamped_array.GetUint8(5));
2318
2319 for (intptr_t i = 0; i < int8_array.Length(); ++i) {
2320 EXPECT_EQ(int8_array.GetUint8(i), uint8_array.GetUint8(i));
2321 }
2322
2323 int8_array.SetInt8(2, -123);
2324 uint8_array.SetUint8(0, 123);
2325 for (intptr_t i = 0; i < int8_array.Length(); ++i) {
2326 EXPECT_EQ(int8_array.GetInt8(i), uint8_array.GetInt8(i));
2327 }
2328
2329 uint8_clamped_array.SetUint8(0, 123);
2330 for (intptr_t i = 0; i < int8_array.Length(); ++i) {
2331 EXPECT_EQ(int8_array.GetUint8(i), uint8_clamped_array.GetUint8(i));
2332 }
2333}
2334
2336 {
2337 const char* url_chars = "builtin:test-case";
2338 const char* source_chars = "This will not compile.";
2339 const String& url = String::Handle(String::New(url_chars));
2340 const String& source = String::Handle(String::New(source_chars));
2342 EXPECT(!script.IsNull());
2343 EXPECT(script.IsScript());
2344 String& str = String::Handle(script.url());
2345 EXPECT_EQ(17, str.Length());
2346 EXPECT_EQ('b', str.CharAt(0));
2347 EXPECT_EQ(':', str.CharAt(7));
2348 EXPECT_EQ('e', str.CharAt(16));
2349 str = script.Source();
2350 EXPECT_EQ(22, str.Length());
2351 EXPECT_EQ('T', str.CharAt(0));
2352 EXPECT_EQ('n', str.CharAt(10));
2353 EXPECT_EQ('.', str.CharAt(21));
2354 }
2355
2356 {
2357 const char* url_chars = "";
2358 // Single line, no terminators.
2359 const char* source_chars = "abc";
2360 const String& url = String::Handle(String::New(url_chars));
2361 const String& source = String::Handle(String::New(source_chars));
2363 EXPECT(!script.IsNull());
2364 EXPECT(script.IsScript());
2365 auto& str = String::Handle(Z);
2366 str = script.GetLine(1);
2367 EXPECT_STREQ("abc", str.ToCString());
2368 str = script.GetSnippet(1, 1, 1, 2);
2369 EXPECT_STREQ("a", str.ToCString());
2370 str = script.GetSnippet(1, 2, 1, 4);
2371 EXPECT_STREQ("bc", str.ToCString());
2372 // Lines not in the source should return the empty string.
2373 str = script.GetLine(-500);
2374 EXPECT_STREQ("", str.ToCString());
2375 str = script.GetLine(0);
2376 EXPECT_STREQ("", str.ToCString());
2377 str = script.GetLine(2);
2378 EXPECT_STREQ("", str.ToCString());
2379 str = script.GetLine(10000);
2380 EXPECT_STREQ("", str.ToCString());
2381 // Snippets not contained within the source should be the null string.
2382 str = script.GetSnippet(-1, 1, 1, 2);
2383 EXPECT(str.IsNull());
2384 str = script.GetSnippet(2, 1, 2, 2);
2385 EXPECT(str.IsNull());
2386 str = script.GetSnippet(1, 1, 1, 5);
2387 EXPECT(str.IsNull());
2388 }
2389
2390 TransitionVMToNative transition(thread);
2391 const char* kScript = "main() {}";
2392 Dart_Handle h_lib = TestCase::LoadTestScript(kScript, nullptr);
2393 EXPECT_VALID(h_lib);
2394 Dart_Handle result = Dart_Invoke(h_lib, NewString("main"), 0, nullptr);
2396}
2397
2399 const int kNumVariables = 5;
2400 const Context& parent_context = Context::Handle(Context::New(0));
2401 const Context& context = Context::Handle(Context::New(kNumVariables));
2402 context.set_parent(parent_context);
2403 EXPECT_EQ(kNumVariables, context.num_variables());
2404 EXPECT(Context::Handle(context.parent()).ptr() == parent_context.ptr());
2405 EXPECT_EQ(0, Context::Handle(context.parent()).num_variables());
2406 EXPECT(Context::Handle(Context::Handle(context.parent()).parent()).IsNull());
2407 Object& variable = Object::Handle(context.At(0));
2408 EXPECT(variable.IsNull());
2409 variable = context.At(kNumVariables - 1);
2410 EXPECT(variable.IsNull());
2411 context.SetAt(0, Smi::Handle(Smi::New(2)));
2412 context.SetAt(2, Smi::Handle(Smi::New(3)));
2413 Smi& smi = Smi::Handle();
2414 smi ^= context.At(0);
2415 EXPECT_EQ(2, smi.Value());
2416 smi ^= context.At(2);
2417 EXPECT_EQ(3, smi.Value());
2418}
2419
2421 // We need an active compiler context to manipulate scopes, since local
2422 // variables and slots can be canonicalized in the compiler state.
2423 CompilerState compiler_state(Thread::Current(), /*is_aot=*/false,
2424 /*is_optimizing=*/false);
2425
2426 const intptr_t parent_scope_function_level = 0;
2427 LocalScope* parent_scope =
2428 new LocalScope(nullptr, parent_scope_function_level, 0);
2429
2430 const intptr_t local_scope_function_level = 1;
2431 LocalScope* local_scope =
2432 new LocalScope(parent_scope, local_scope_function_level, 0);
2433
2434 const Type& dynamic_type = Type::ZoneHandle(Type::DynamicType());
2435 const String& ta = Symbols::FunctionTypeArgumentsVar();
2436 LocalVariable* var_ta = new LocalVariable(
2437 TokenPosition::kNoSource, TokenPosition::kNoSource, ta, dynamic_type);
2438 parent_scope->AddVariable(var_ta);
2439
2440 const String& a = String::ZoneHandle(Symbols::New(thread, "a"));
2441 LocalVariable* var_a = new LocalVariable(
2442 TokenPosition::kNoSource, TokenPosition::kNoSource, a, dynamic_type);
2443 parent_scope->AddVariable(var_a);
2444
2445 const String& b = String::ZoneHandle(Symbols::New(thread, "b"));
2446 LocalVariable* var_b = new LocalVariable(
2447 TokenPosition::kNoSource, TokenPosition::kNoSource, b, dynamic_type);
2448 local_scope->AddVariable(var_b);
2449
2450 const String& c = String::ZoneHandle(Symbols::New(thread, "c"));
2451 LocalVariable* var_c = new LocalVariable(
2452 TokenPosition::kNoSource, TokenPosition::kNoSource, c, dynamic_type);
2453 parent_scope->AddVariable(var_c);
2454
2455 bool test_only = false; // Please, insert alias.
2456 var_ta = local_scope->LookupVariable(ta, LocalVariable::kNoKernelOffset,
2457 test_only);
2458 EXPECT(var_ta->is_captured());
2459 EXPECT_EQ(parent_scope_function_level, var_ta->owner()->function_level());
2461 var_ta); // Alias.
2462
2463 var_a =
2464 local_scope->LookupVariable(a, LocalVariable::kNoKernelOffset, test_only);
2465 EXPECT(var_a->is_captured());
2466 EXPECT_EQ(parent_scope_function_level, var_a->owner()->function_level());
2468 var_a); // Alias.
2469
2470 var_b =
2471 local_scope->LookupVariable(b, LocalVariable::kNoKernelOffset, test_only);
2472 EXPECT(!var_b->is_captured());
2473 EXPECT_EQ(local_scope_function_level, var_b->owner()->function_level());
2475 var_b);
2476
2477 test_only = true; // Please, do not insert alias.
2478 var_c =
2479 local_scope->LookupVariable(c, LocalVariable::kNoKernelOffset, test_only);
2480 EXPECT(!var_c->is_captured());
2481 EXPECT_EQ(parent_scope_function_level, var_c->owner()->function_level());
2482 // c is not in local_scope.
2484 nullptr);
2485
2486 test_only = false; // Please, insert alias.
2487 var_c =
2488 local_scope->LookupVariable(c, LocalVariable::kNoKernelOffset, test_only);
2489 EXPECT(var_c->is_captured());
2490
2491 EXPECT_EQ(4, local_scope->num_variables()); // ta, a, b, c.
2492 EXPECT_EQ(3, local_scope->NumCapturedVariables()); // ta, a, c.
2493
2494 const VariableIndex first_parameter_index(0);
2495 const int num_parameters = 0;
2496 const VariableIndex first_local_index(-1);
2497 bool found_captured_vars = false;
2498 VariableIndex next_index = parent_scope->AllocateVariables(
2499 Function::null_function(), first_parameter_index, num_parameters,
2500 first_local_index, nullptr, &found_captured_vars);
2501 // Variables a, c and var_ta are captured, therefore are not allocated in
2502 // frame.
2503 EXPECT_EQ(0, next_index.value() -
2504 first_local_index.value()); // Indices in frame < 0.
2505 const intptr_t parent_scope_context_level = 1;
2506 EXPECT_EQ(parent_scope_context_level, parent_scope->context_level());
2507 EXPECT(found_captured_vars);
2508
2509 const intptr_t local_scope_context_level = 5;
2510 const ContextScope& context_scope =
2512 Function::null_function(), local_scope_context_level));
2513 LocalScope* outer_scope = LocalScope::RestoreOuterScope(context_scope);
2514 EXPECT_EQ(3, outer_scope->num_variables());
2515
2516 var_ta = outer_scope->LocalLookupVariable(ta, LocalVariable::kNoKernelOffset);
2517 EXPECT(var_ta->is_captured());
2518 EXPECT_EQ(0, var_ta->index().value()); // First index.
2519 EXPECT_EQ(parent_scope_context_level - local_scope_context_level,
2520 var_ta->owner()->context_level()); // Adjusted context level.
2521
2523 EXPECT(var_a->is_captured());
2524 EXPECT_EQ(1, var_a->index().value()); // First index.
2525 EXPECT_EQ(parent_scope_context_level - local_scope_context_level,
2526 var_a->owner()->context_level()); // Adjusted context level.
2527
2528 // var b was not captured.
2530 nullptr);
2531
2532 var_c = outer_scope->LocalLookupVariable(c, LocalVariable::kNoKernelOffset);
2533 EXPECT(var_c->is_captured());
2534 EXPECT_EQ(2, var_c->index().value());
2535 EXPECT_EQ(parent_scope_context_level - local_scope_context_level,
2536 var_c->owner()->context_level()); // Adjusted context level.
2537}
2538
2540 // Allocate the class first.
2541 const String& class_name = String::Handle(Symbols::New(thread, "MyClass"));
2542 const Script& script = Script::Handle();
2544 const Array& functions = Array::Handle(Array::New(1));
2545
2546 const Context& context = Context::Handle(Context::New(0));
2547 Function& parent = Function::Handle();
2548 const String& parent_name = String::Handle(Symbols::New(thread, "foo_papa"));
2550 parent = Function::New(signature, parent_name,
2551 UntaggedFunction::kRegularFunction, false, false,
2552 false, false, false, cls, TokenPosition::kMinSource);
2553 functions.SetAt(0, parent);
2554 {
2555 SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
2556 cls.SetFunctions(functions);
2557 cls.Finalize();
2558 }
2559
2561 const String& function_name = String::Handle(Symbols::New(thread, "foo"));
2564 signature = function.signature();
2565 signature.set_result_type(Object::dynamic_type());
2566 signature ^= ClassFinalizer::FinalizeType(signature);
2567 function.SetSignature(signature);
2569 Closure::New(Object::null_type_arguments(), Object::null_type_arguments(),
2570 function, context));
2571 const Class& closure_class = Class::Handle(closure.clazz());
2572 EXPECT_EQ(closure_class.id(), kClosureCid);
2573 const Function& closure_function = Function::Handle(closure.function());
2574 EXPECT_EQ(closure_function.ptr(), function.ptr());
2575 const Context& closure_context = Context::Handle(closure.GetContext());
2576 EXPECT_EQ(closure_context.ptr(), context.ptr());
2577}
2578
2579ISOLATE_UNIT_TEST_CASE(ObjectPrinting) {
2580 // Simple Smis.
2581 EXPECT_STREQ("2", Smi::Handle(Smi::New(2)).ToCString());
2582 EXPECT_STREQ("-15", Smi::Handle(Smi::New(-15)).ToCString());
2583
2584 // bool class and true/false values.
2585 ObjectStore* object_store = IsolateGroup::Current()->object_store();
2586 const Class& bool_class = Class::Handle(object_store->bool_class());
2587 EXPECT_STREQ("Library:'dart:core' Class: bool", bool_class.ToCString());
2588 EXPECT_STREQ("true", Bool::True().ToCString());
2589 EXPECT_STREQ("false", Bool::False().ToCString());
2590
2591 // Strings.
2592 EXPECT_STREQ("Sugarbowl",
2593 String::Handle(String::New("Sugarbowl")).ToCString());
2594}
2595
2597 // Ensure that null handles have the correct C++ vtable setup.
2598 Zone* zone = Thread::Current()->zone();
2599 const String& str1 = String::Handle(zone);
2600 EXPECT(str1.IsString());
2601 EXPECT(str1.IsNull());
2602 const String& str2 = String::CheckedHandle(zone, Object::null());
2603 EXPECT(str2.IsString());
2604 EXPECT(str2.IsNull());
2605 String& str3 = String::Handle(zone);
2606 str3 ^= Object::null();
2607 EXPECT(str3.IsString());
2608 EXPECT(str3.IsNull());
2609 EXPECT(!str3.IsOneByteString());
2610 str3 = String::New("Steep and Deep!");
2611 EXPECT(str3.IsString());
2612 EXPECT(str3.IsOneByteString());
2613 str3 = OneByteString::null();
2614 EXPECT(str3.IsString());
2615 EXPECT(!str3.IsOneByteString());
2616}
2617
2618static LibraryPtr CreateDummyLibrary(const String& library_name) {
2619 return Library::New(library_name);
2620}
2621
2622static FunctionPtr CreateFunction(const char* name) {
2623 Thread* thread = Thread::Current();
2624 const String& class_name = String::Handle(Symbols::New(thread, "ownerClass"));
2625 const String& lib_name = String::Handle(Symbols::New(thread, "ownerLibrary"));
2626 const Script& script = Script::Handle();
2627 const Class& owner_class =
2629 const Library& owner_library = Library::Handle(CreateDummyLibrary(lib_name));
2630 owner_class.set_library(owner_library);
2633 return Function::New(signature, function_name,
2634 UntaggedFunction::kRegularFunction, true, false, false,
2635 false, false, owner_class, TokenPosition::kMinSource);
2636}
2637
2638// Test for Code and Instruction object creation.
2640 extern void GenerateIncrement(compiler::Assembler * assembler);
2641 compiler::ObjectPoolBuilder object_pool_builder;
2642 compiler::Assembler _assembler_(&object_pool_builder);
2643 GenerateIncrement(&_assembler_);
2644 const Function& function = Function::Handle(CreateFunction("Test_Code"));
2645 SafepointWriteRwLocker locker(thread,
2646 thread->isolate_group()->program_lock());
2648 function, nullptr, &_assembler_, Code::PoolAttachment::kAttachPool));
2649 function.AttachCode(code);
2650 const Instructions& instructions = Instructions::Handle(code.instructions());
2651 uword payload_start = instructions.PayloadStart();
2652 EXPECT_EQ(instructions.ptr(), Instructions::FromPayloadStart(payload_start));
2653 const Object& result =
2654 Object::Handle(DartEntry::InvokeFunction(function, Array::empty_array()));
2655 EXPECT_EQ(1, Smi::Cast(result).Value());
2656}
2657
2658// Test for immutability of generated instructions. The test crashes with a
2659// segmentation fault when writing into it.
2661 extern void GenerateIncrement(compiler::Assembler * assembler);
2662 compiler::ObjectPoolBuilder object_pool_builder;
2663 compiler::Assembler _assembler_(&object_pool_builder);
2664 GenerateIncrement(&_assembler_);
2665 const Function& function = Function::Handle(CreateFunction("Test_Code"));
2666 SafepointWriteRwLocker locker(thread,
2667 thread->isolate_group()->program_lock());
2669 function, nullptr, &_assembler_, Code::PoolAttachment::kAttachPool));
2670 function.AttachCode(code);
2671 Instructions& instructions = Instructions::Handle(code.instructions());
2672 uword payload_start = instructions.PayloadStart();
2673 EXPECT_EQ(instructions.ptr(), Instructions::FromPayloadStart(payload_start));
2674 // Try writing into the generated code, expected to crash.
2675 *(reinterpret_cast<char*>(payload_start) + 1) = 1;
2676 if (!FLAG_write_protect_code) {
2677 // Since this test is expected to crash, crash if write protection of code
2678 // is switched off.
2679 FATAL("Test requires --write-protect-code; skip by forcing expected crash");
2680 }
2681}
2682
2684 public:
2685 static void SetInstructions(const Code& code,
2686 const Instructions& instructions,
2687 uword unchecked_offset) {
2688 code.SetActiveInstructions(instructions, unchecked_offset);
2689 code.set_instructions(instructions);
2690 }
2691};
2692
2693// Test for Embedded String object in the instructions.
2694ISOLATE_UNIT_TEST_CASE(EmbedStringInCode) {
2695 extern void GenerateEmbedStringInCode(compiler::Assembler * assembler,
2696 const char* str);
2697 const char* kHello = "Hello World!";
2698 word expected_length = static_cast<word>(strlen(kHello));
2699 compiler::ObjectPoolBuilder object_pool_builder;
2700 compiler::Assembler _assembler_(&object_pool_builder);
2701 GenerateEmbedStringInCode(&_assembler_, kHello);
2702 const Function& function =
2703 Function::Handle(CreateFunction("Test_EmbedStringInCode"));
2704 SafepointWriteRwLocker locker(thread,
2705 thread->isolate_group()->program_lock());
2707 function, nullptr, &_assembler_, Code::PoolAttachment::kAttachPool));
2708 function.AttachCode(code);
2709 const Object& result =
2710 Object::Handle(DartEntry::InvokeFunction(function, Array::empty_array()));
2711 EXPECT(result.ptr()->IsHeapObject());
2712 String& string_object = String::Handle();
2713 string_object ^= result.ptr();
2714 EXPECT(string_object.Length() == expected_length);
2715 for (int i = 0; i < expected_length; i++) {
2716 EXPECT(string_object.CharAt(i) == kHello[i]);
2717 }
2718}
2719
2720// Test for Embedded Smi object in the instructions.
2721ISOLATE_UNIT_TEST_CASE(EmbedSmiInCode) {
2722 extern void GenerateEmbedSmiInCode(compiler::Assembler * assembler,
2723 intptr_t value);
2724 const intptr_t kSmiTestValue = 5;
2725 compiler::ObjectPoolBuilder object_pool_builder;
2726 compiler::Assembler _assembler_(&object_pool_builder);
2727 GenerateEmbedSmiInCode(&_assembler_, kSmiTestValue);
2728 const Function& function =
2729 Function::Handle(CreateFunction("Test_EmbedSmiInCode"));
2730 SafepointWriteRwLocker locker(thread,
2731 thread->isolate_group()->program_lock());
2733 function, nullptr, &_assembler_, Code::PoolAttachment::kAttachPool));
2734 function.AttachCode(code);
2735 const Object& result =
2736 Object::Handle(DartEntry::InvokeFunction(function, Array::empty_array()));
2737 EXPECT(Smi::Cast(result).Value() == kSmiTestValue);
2738}
2739
2740#if defined(ARCH_IS_64_BIT) && !defined(DART_COMPRESSED_POINTERS)
2741// Test for Embedded Smi object in the instructions.
2742ISOLATE_UNIT_TEST_CASE(EmbedSmiIn64BitCode) {
2743 extern void GenerateEmbedSmiInCode(compiler::Assembler * assembler,
2744 intptr_t value);
2745 const intptr_t kSmiTestValue = DART_INT64_C(5) << 32;
2746 compiler::ObjectPoolBuilder object_pool_builder;
2747 compiler::Assembler _assembler_(&object_pool_builder);
2748 GenerateEmbedSmiInCode(&_assembler_, kSmiTestValue);
2749 const Function& function =
2750 Function::Handle(CreateFunction("Test_EmbedSmiIn64BitCode"));
2751 SafepointWriteRwLocker locker(thread,
2752 thread->isolate_group()->program_lock());
2754 function, nullptr, &_assembler_, Code::PoolAttachment::kAttachPool));
2755 function.AttachCode(code);
2756 const Object& result =
2757 Object::Handle(DartEntry::InvokeFunction(function, Array::empty_array()));
2758 EXPECT(Smi::Cast(result).Value() == kSmiTestValue);
2759}
2760#endif // ARCH_IS_64_BIT && !DART_COMPRESSED_POINTERS
2761
2763 const int kNumEntries = 4;
2764 // Add an exception handler table to the code.
2765 ExceptionHandlers& exception_handlers = ExceptionHandlers::Handle();
2766 exception_handlers ^= ExceptionHandlers::New(kNumEntries);
2767 const bool kNeedsStackTrace = true;
2768 const bool kNoStackTrace = false;
2769 exception_handlers.SetHandlerInfo(0, -1, 20u, kNeedsStackTrace, false, true);
2770 exception_handlers.SetHandlerInfo(1, 0, 30u, kNeedsStackTrace, false, true);
2771 exception_handlers.SetHandlerInfo(2, -1, 40u, kNoStackTrace, true, true);
2772 exception_handlers.SetHandlerInfo(3, 1, 150u, kNoStackTrace, true, true);
2773
2774 extern void GenerateIncrement(compiler::Assembler * assembler);
2775 compiler::ObjectPoolBuilder object_pool_builder;
2776 compiler::Assembler _assembler_(&object_pool_builder);
2777 GenerateIncrement(&_assembler_);
2778 SafepointWriteRwLocker locker(thread,
2779 thread->isolate_group()->program_lock());
2781 Function::Handle(CreateFunction("Test_Code")), nullptr, &_assembler_,
2783 code.set_exception_handlers(exception_handlers);
2784
2785 // Verify the exception handler table entries by accessing them.
2786 const ExceptionHandlers& handlers =
2787 ExceptionHandlers::Handle(code.exception_handlers());
2788 EXPECT_EQ(kNumEntries, handlers.num_entries());
2790 handlers.GetHandlerInfo(0, &info);
2791 EXPECT_EQ(-1, handlers.OuterTryIndex(0));
2792 EXPECT_EQ(-1, info.outer_try_index);
2793 EXPECT_EQ(20u, handlers.HandlerPCOffset(0));
2794 EXPECT(handlers.NeedsStackTrace(0));
2795 EXPECT(!handlers.HasCatchAll(0));
2796 EXPECT_EQ(20u, info.handler_pc_offset);
2797 EXPECT_EQ(1, handlers.OuterTryIndex(3));
2798 EXPECT_EQ(150u, handlers.HandlerPCOffset(3));
2799 EXPECT(!handlers.NeedsStackTrace(3));
2800 EXPECT(handlers.HasCatchAll(3));
2801}
2802
2804 DescriptorList* builder = new DescriptorList(thread->zone());
2805
2806 // kind, pc_offset, deopt_id, token_pos, try_index, yield_index
2807 builder->AddDescriptor(UntaggedPcDescriptors::kOther, 10, 1,
2808 TokenPosition::Deserialize(20), 1, 1);
2809 builder->AddDescriptor(UntaggedPcDescriptors::kDeopt, 20, 2,
2810 TokenPosition::Deserialize(30), 0, -1);
2811 builder->AddDescriptor(UntaggedPcDescriptors::kOther, 30, 3,
2812 TokenPosition::Deserialize(40), 1, 10);
2813 builder->AddDescriptor(UntaggedPcDescriptors::kOther, 10, 4,
2814 TokenPosition::Deserialize(40), 2, 20);
2815 builder->AddDescriptor(UntaggedPcDescriptors::kOther, 10, 5,
2816 TokenPosition::Deserialize(80), 3, 30);
2817 builder->AddDescriptor(UntaggedPcDescriptors::kOther, 80, 6,
2818 TokenPosition::Deserialize(150), 3, 30);
2819
2820 PcDescriptors& descriptors = PcDescriptors::Handle();
2821 descriptors ^= builder->FinalizePcDescriptors(0);
2822
2823 extern void GenerateIncrement(compiler::Assembler * assembler);
2824 compiler::ObjectPoolBuilder object_pool_builder;
2825 compiler::Assembler _assembler_(&object_pool_builder);
2826 GenerateIncrement(&_assembler_);
2827 SafepointWriteRwLocker locker(thread,
2828 thread->isolate_group()->program_lock());
2830 Function::Handle(CreateFunction("Test_Code")), nullptr, &_assembler_,
2832 code.set_pc_descriptors(descriptors);
2833
2834 // Verify the PcDescriptor entries by accessing them.
2835 const PcDescriptors& pc_descs = PcDescriptors::Handle(code.pc_descriptors());
2836 PcDescriptors::Iterator iter(pc_descs, UntaggedPcDescriptors::kAnyKind);
2837
2838 EXPECT_EQ(true, iter.MoveNext());
2839 EXPECT_EQ(1, iter.YieldIndex());
2840 EXPECT_EQ(20, iter.TokenPos().Pos());
2841 EXPECT_EQ(1, iter.TryIndex());
2842 EXPECT_EQ(static_cast<uword>(10), iter.PcOffset());
2843 EXPECT_EQ(1, iter.DeoptId());
2844 EXPECT_EQ(UntaggedPcDescriptors::kOther, iter.Kind());
2845
2846 EXPECT_EQ(true, iter.MoveNext());
2847 EXPECT_EQ(-1, iter.YieldIndex());
2848 EXPECT_EQ(30, iter.TokenPos().Pos());
2849 EXPECT_EQ(UntaggedPcDescriptors::kDeopt, iter.Kind());
2850
2851 EXPECT_EQ(true, iter.MoveNext());
2852 EXPECT_EQ(10, iter.YieldIndex());
2853 EXPECT_EQ(40, iter.TokenPos().Pos());
2854
2855 EXPECT_EQ(true, iter.MoveNext());
2856 EXPECT_EQ(20, iter.YieldIndex());
2857 EXPECT_EQ(40, iter.TokenPos().Pos());
2858
2859 EXPECT_EQ(true, iter.MoveNext());
2860 EXPECT_EQ(30, iter.YieldIndex());
2861 EXPECT_EQ(80, iter.TokenPos().Pos());
2862
2863 EXPECT_EQ(true, iter.MoveNext());
2864 EXPECT_EQ(30, iter.YieldIndex());
2865 EXPECT_EQ(150, iter.TokenPos().Pos());
2866
2867 EXPECT_EQ(3, iter.TryIndex());
2868 EXPECT_EQ(static_cast<uword>(80), iter.PcOffset());
2869 EXPECT_EQ(150, iter.TokenPos().Pos());
2870 EXPECT_EQ(UntaggedPcDescriptors::kOther, iter.Kind());
2871
2872 EXPECT_EQ(false, iter.MoveNext());
2873}
2874
2875ISOLATE_UNIT_TEST_CASE(PcDescriptorsLargeDeltas) {
2876 DescriptorList* builder = new DescriptorList(thread->zone());
2877
2878 // kind, pc_offset, deopt_id, token_pos, try_index
2879 builder->AddDescriptor(UntaggedPcDescriptors::kOther, 100, 1,
2880 TokenPosition::Deserialize(200), 1, 10);
2881 builder->AddDescriptor(UntaggedPcDescriptors::kDeopt, 200, 2,
2882 TokenPosition::Deserialize(300), 0, -1);
2883 builder->AddDescriptor(UntaggedPcDescriptors::kOther, 300, 3,
2884 TokenPosition::Deserialize(400), 1, 10);
2885 builder->AddDescriptor(UntaggedPcDescriptors::kOther, 100, 4,
2886 TokenPosition::Deserialize(0), 2, 20);
2887 builder->AddDescriptor(UntaggedPcDescriptors::kOther, 100, 5,
2888 TokenPosition::Deserialize(800), 3, 30);
2889 builder->AddDescriptor(UntaggedPcDescriptors::kOther, 800, 6,
2890 TokenPosition::Deserialize(150), 3, 30);
2891
2892 PcDescriptors& descriptors = PcDescriptors::Handle();
2893 descriptors ^= builder->FinalizePcDescriptors(0);
2894
2895 extern void GenerateIncrement(compiler::Assembler * assembler);
2896 compiler::ObjectPoolBuilder object_pool_builder;
2897 compiler::Assembler _assembler_(&object_pool_builder);
2898 GenerateIncrement(&_assembler_);
2899 SafepointWriteRwLocker locker(thread,
2900 thread->isolate_group()->program_lock());
2902 Function::Handle(CreateFunction("Test_Code")), nullptr, &_assembler_,
2904 code.set_pc_descriptors(descriptors);
2905
2906 // Verify the PcDescriptor entries by accessing them.
2907 const PcDescriptors& pc_descs = PcDescriptors::Handle(code.pc_descriptors());
2908 PcDescriptors::Iterator iter(pc_descs, UntaggedPcDescriptors::kAnyKind);
2909
2910 EXPECT_EQ(true, iter.MoveNext());
2911 EXPECT_EQ(10, iter.YieldIndex());
2912 EXPECT_EQ(200, iter.TokenPos().Pos());
2913 EXPECT_EQ(1, iter.TryIndex());
2914 EXPECT_EQ(static_cast<uword>(100), iter.PcOffset());
2915 EXPECT_EQ(1, iter.DeoptId());
2916 EXPECT_EQ(UntaggedPcDescriptors::kOther, iter.Kind());
2917
2918 EXPECT_EQ(true, iter.MoveNext());
2919 EXPECT_EQ(-1, iter.YieldIndex());
2920 EXPECT_EQ(300, iter.TokenPos().Pos());
2921 EXPECT_EQ(UntaggedPcDescriptors::kDeopt, iter.Kind());
2922
2923 EXPECT_EQ(true, iter.MoveNext());
2924 EXPECT_EQ(10, iter.YieldIndex());
2925 EXPECT_EQ(400, iter.TokenPos().Pos());
2926
2927 EXPECT_EQ(true, iter.MoveNext());
2928 EXPECT_EQ(20, iter.YieldIndex());
2929 EXPECT_EQ(0, iter.TokenPos().Pos());
2930
2931 EXPECT_EQ(true, iter.MoveNext());
2932 EXPECT_EQ(30, iter.YieldIndex());
2933 EXPECT_EQ(800, iter.TokenPos().Pos());
2934
2935 EXPECT_EQ(true, iter.MoveNext());
2936 EXPECT_EQ(30, iter.YieldIndex());
2937 EXPECT_EQ(150, iter.TokenPos().Pos());
2938
2939 EXPECT_EQ(3, iter.TryIndex());
2940 EXPECT_EQ(static_cast<uword>(800), iter.PcOffset());
2941 EXPECT_EQ(150, iter.TokenPos().Pos());
2942 EXPECT_EQ(UntaggedPcDescriptors::kOther, iter.Kind());
2943
2944 EXPECT_EQ(false, iter.MoveNext());
2945}
2946
2947static ClassPtr CreateTestClass(const char* name) {
2948 const String& class_name =
2950 const Class& cls =
2952 return cls.ptr();
2953}
2954
2955static FieldPtr CreateTestField(const char* name) {
2956 auto thread = Thread::Current();
2957 const Class& cls = Class::Handle(CreateTestClass("global:"));
2958 const String& field_name = String::Handle(Symbols::New(thread, name));
2959 const Field& field = Field::Handle(Field::New(
2960 field_name, true, false, false, true, false, cls, Object::dynamic_type(),
2962 {
2963 SafepointWriteRwLocker locker(thread,
2964 thread->isolate_group()->program_lock());
2965 thread->isolate_group()->RegisterStaticField(field, Object::sentinel());
2966 }
2967 return field.ptr();
2968}
2969
2971 Class& ae66 = Class::ZoneHandle(CreateTestClass("Ae6/6"));
2972 Class& re44 = Class::ZoneHandle(CreateTestClass("Re4/4"));
2973 Field& ce68 = Field::ZoneHandle(CreateTestField("Ce6/8"));
2975 String& url = String::ZoneHandle(String::New("SBB"));
2976 Library& lib = Library::Handle(Library::New(url));
2977 lib.AddClass(ae66);
2978 lib.AddObject(ce68, String::ZoneHandle(ce68.name()));
2979 lib.AddClass(re44);
2980 lib.AddObject(tee, String::ZoneHandle(tee.name()));
2981 ClassDictionaryIterator iterator(lib);
2982 int count = 0;
2983 Class& cls = Class::Handle();
2984 while (iterator.HasNext()) {
2985 cls = iterator.GetNextClass();
2986 EXPECT((cls.ptr() == ae66.ptr()) || (cls.ptr() == re44.ptr()));
2987 count++;
2988 }
2989 EXPECT(count == 2);
2990}
2991
2992static FunctionPtr GetDummyTarget(const char* name) {
2993 const String& function_name =
2995 const Class& cls =
2997 const bool is_static = false;
2998 const bool is_const = false;
2999 const bool is_abstract = false;
3000 const bool is_external = false;
3001 const bool is_native = false;
3003 return Function::New(signature, function_name,
3004 UntaggedFunction::kRegularFunction, is_static, is_const,
3005 is_abstract, is_external, is_native, cls,
3007}
3008
3011 const intptr_t id = 12;
3012 const intptr_t num_args_tested = 1;
3013 const String& target_name = String::Handle(Symbols::New(thread, "Thun"));
3014 const intptr_t kTypeArgsLen = 0;
3015 const intptr_t kNumArgs = 1;
3016 const Array& args_descriptor = Array::Handle(ArgumentsDescriptor::NewBoxed(
3017 kTypeArgsLen, kNumArgs, Object::null_array()));
3018 ICData& o1 = ICData::Handle();
3019 o1 = ICData::New(function, target_name, args_descriptor, id, num_args_tested,
3020 ICData::kInstance);
3021 EXPECT_EQ(1, o1.NumArgsTested());
3022 EXPECT_EQ(id, o1.deopt_id());
3023 EXPECT_EQ(function.ptr(), o1.Owner());
3024 EXPECT_EQ(0, o1.NumberOfChecks());
3025 EXPECT_EQ(target_name.ptr(), o1.target_name());
3026 EXPECT_EQ(args_descriptor.ptr(), o1.arguments_descriptor());
3027
3028 const Function& target1 = Function::Handle(GetDummyTarget("Thun"));
3029 o1.AddReceiverCheck(kSmiCid, target1);
3030 EXPECT_EQ(1, o1.NumberOfChecks());
3031 EXPECT_EQ(1, o1.NumberOfUsedChecks());
3032 intptr_t test_class_id = -1;
3033 Function& test_target = Function::Handle();
3034 o1.GetOneClassCheckAt(0, &test_class_id, &test_target);
3035 EXPECT_EQ(kSmiCid, test_class_id);
3036 EXPECT_EQ(target1.ptr(), test_target.ptr());
3037 EXPECT_EQ(kSmiCid, o1.GetCidAt(0));
3038 GrowableArray<intptr_t> test_class_ids;
3039 o1.GetCheckAt(0, &test_class_ids, &test_target);
3040 EXPECT_EQ(1, test_class_ids.length());
3041 EXPECT_EQ(kSmiCid, test_class_ids[0]);
3042 EXPECT_EQ(target1.ptr(), test_target.ptr());
3043
3044 const Function& target2 = Function::Handle(GetDummyTarget("Thun"));
3045 o1.AddReceiverCheck(kDoubleCid, target2);
3046 EXPECT_EQ(2, o1.NumberOfChecks());
3047 EXPECT_EQ(2, o1.NumberOfUsedChecks());
3048 o1.GetOneClassCheckAt(1, &test_class_id, &test_target);
3049 EXPECT_EQ(kDoubleCid, test_class_id);
3050 EXPECT_EQ(target2.ptr(), test_target.ptr());
3051 EXPECT_EQ(kDoubleCid, o1.GetCidAt(1));
3052
3053 o1.AddReceiverCheck(kMintCid, target2);
3054 EXPECT_EQ(3, o1.NumberOfUsedChecks());
3055 o1.SetCountAt(o1.NumberOfChecks() - 1, 0);
3056 EXPECT_EQ(2, o1.NumberOfUsedChecks());
3057
3058 ICData& o2 = ICData::Handle();
3059 o2 = ICData::New(function, target_name, args_descriptor, 57, 2,
3060 ICData::kInstance);
3061 EXPECT_EQ(2, o2.NumArgsTested());
3062 EXPECT_EQ(57, o2.deopt_id());
3063 EXPECT_EQ(function.ptr(), o2.Owner());
3064 EXPECT_EQ(0, o2.NumberOfChecks());
3066 classes.Add(kSmiCid);
3067 classes.Add(kSmiCid);
3068 o2.AddCheck(classes, target1);
3069 EXPECT_EQ(1, o2.NumberOfChecks());
3070 o2.GetCheckAt(0, &test_class_ids, &test_target);
3071 EXPECT_EQ(2, test_class_ids.length());
3072 EXPECT_EQ(kSmiCid, test_class_ids[0]);
3073 EXPECT_EQ(kSmiCid, test_class_ids[1]);
3074 EXPECT_EQ(target1.ptr(), test_target.ptr());
3075
3076 // Check ICData for unoptimized static calls.
3077 const intptr_t kNumArgsChecked = 0;
3078 const ICData& scall_icdata = ICData::Handle(
3079 ICData::NewForStaticCall(function, target1, args_descriptor, 57,
3080 kNumArgsChecked, ICData::kInstance));
3081 EXPECT_EQ(target1.ptr(), scall_icdata.GetTargetAt(0));
3082}
3083
3085 SafepointMutexLocker ml(thread->isolate_group()->subtype_test_cache_mutex());
3086
3087 String& class1_name = String::Handle(Symbols::New(thread, "EmptyClass1"));
3089 const Class& empty_class1 =
3090 Class::Handle(CreateDummyClass(class1_name, script));
3091 String& class2_name = String::Handle(Symbols::New(thread, "EmptyClass2"));
3092 const Class& empty_class2 =
3093 Class::Handle(CreateDummyClass(class2_name, script));
3096 EXPECT(!cache.IsNull());
3097 EXPECT_EQ(0, cache.NumberOfChecks());
3098 const Object& class_id_or_fun = Object::Handle(Smi::New(empty_class1.id()));
3099 const AbstractType& dest_type =
3106 cache.AddCheck(class_id_or_fun, dest_type, targ_0, targ_1, targ_2, targ_3,
3107 targ_4, Bool::True());
3108 EXPECT_EQ(1, cache.NumberOfChecks());
3109 Object& test_class_id_or_fun = Object::Handle();
3110 AbstractType& test_dest_type = AbstractType::Handle();
3111 TypeArguments& test_targ_0 = TypeArguments::Handle();
3112 TypeArguments& test_targ_1 = TypeArguments::Handle();
3113 TypeArguments& test_targ_2 = TypeArguments::Handle();
3114 TypeArguments& test_targ_3 = TypeArguments::Handle();
3115 TypeArguments& test_targ_4 = TypeArguments::Handle();
3116 Bool& test_result = Bool::Handle();
3117 cache.GetCheck(0, &test_class_id_or_fun, &test_dest_type, &test_targ_0,
3118 &test_targ_1, &test_targ_2, &test_targ_3, &test_targ_4,
3119 &test_result);
3120 EXPECT_EQ(class_id_or_fun.ptr(), test_class_id_or_fun.ptr());
3121 EXPECT_EQ(dest_type.ptr(), test_dest_type.ptr());
3122 EXPECT_EQ(targ_0.ptr(), test_targ_0.ptr());
3123 EXPECT_EQ(targ_1.ptr(), test_targ_1.ptr());
3124 EXPECT_EQ(targ_2.ptr(), test_targ_2.ptr());
3125 EXPECT_EQ(targ_3.ptr(), test_targ_3.ptr());
3126 EXPECT_EQ(targ_4.ptr(), test_targ_4.ptr());
3127 EXPECT_EQ(Bool::True().ptr(), test_result.ptr());
3128}
3129
3131 const auto& name = String::Handle(Symbols::New(thread, "name"));
3132 const auto& args_descriptor =
3133 Array::Handle(ArgumentsDescriptor::NewBoxed(1, 1, Object::null_array()));
3134
3135 const auto& cidA = Smi::Handle(Smi::New(1));
3136 const auto& cidB = Smi::Handle(Smi::New(2));
3137
3138 const auto& valueA = Smi::Handle(Smi::New(42));
3139 const auto& valueB = Smi::Handle(Smi::New(43));
3140
3141 // Test normal insert/lookup methods.
3142 {
3143 const auto& cache =
3144 MegamorphicCache::Handle(MegamorphicCache::New(name, args_descriptor));
3145
3146 EXPECT(cache.Lookup(cidA) == Object::null());
3147 cache.EnsureContains(cidA, valueA);
3148 EXPECT(cache.Lookup(cidA) == valueA.ptr());
3149
3150 EXPECT(cache.Lookup(cidB) == Object::null());
3151 cache.EnsureContains(cidB, valueB);
3152 EXPECT(cache.Lookup(cidB) == valueB.ptr());
3153 }
3154
3155 // Try to insert many keys to hit collisions & growth.
3156 {
3157 const auto& cache =
3158 MegamorphicCache::Handle(MegamorphicCache::New(name, args_descriptor));
3159
3160 auto& cid = Smi::Handle();
3161 auto& value = Object::Handle();
3162 for (intptr_t i = 0; i < 100; ++i) {
3163 cid = Smi::New(100 * i);
3164 if (cid.Value() == kIllegalCid) continue;
3165
3166 value = Smi::New(i);
3167 cache.EnsureContains(cid, value);
3168 }
3169 auto& expected = Object::Handle();
3170 for (intptr_t i = 0; i < 100; ++i) {
3171 cid = Smi::New(100 * i);
3172 if (cid.Value() == kIllegalCid) continue;
3173
3174 expected = Smi::New(i);
3175 value = cache.Lookup(cid);
3176 EXPECT(Smi::Cast(value).Equals(Smi::Cast(expected)));
3177 }
3178 }
3179}
3180
3182 const String& f = String::Handle(String::New("oneField"));
3183 const String& getter_f = String::Handle(Field::GetterName(f));
3184 const String& setter_f = String::Handle(Field::SetterName(f));
3187 EXPECT(Field::IsGetterName(getter_f));
3188 EXPECT(!Field::IsSetterName(getter_f));
3189 EXPECT(!Field::IsGetterName(setter_f));
3190 EXPECT(Field::IsSetterName(setter_f));
3191 EXPECT_STREQ(f.ToCString(),
3193 EXPECT_STREQ(f.ToCString(),
3195}
3196
3197// Expose helper function from object.cc for testing.
3198bool EqualsIgnoringPrivate(const String& name, const String& private_name);
3199
3201 String& mangled_name = String::Handle();
3202 String& bare_name = String::Handle();
3203
3204 // Simple matches.
3205 mangled_name = OneByteString::New("foo");
3206 bare_name = OneByteString::New("foo");
3207 EXPECT(String::EqualsIgnoringPrivateKey(mangled_name, bare_name));
3208
3209 mangled_name = OneByteString::New("foo.");
3210 bare_name = OneByteString::New("foo.");
3211 EXPECT(String::EqualsIgnoringPrivateKey(mangled_name, bare_name));
3212
3213 mangled_name = OneByteString::New("foo.named");
3214 bare_name = OneByteString::New("foo.named");
3215 EXPECT(String::EqualsIgnoringPrivateKey(mangled_name, bare_name));
3216
3217 // Simple mismatches.
3218 mangled_name = OneByteString::New("bar");
3219 bare_name = OneByteString::New("foo");
3220 EXPECT(!String::EqualsIgnoringPrivateKey(mangled_name, bare_name));
3221
3222 mangled_name = OneByteString::New("foo.");
3223 bare_name = OneByteString::New("foo");
3224 EXPECT(!String::EqualsIgnoringPrivateKey(mangled_name, bare_name));
3225
3226 mangled_name = OneByteString::New("foo");
3227 bare_name = OneByteString::New("foo.");
3228 EXPECT(!String::EqualsIgnoringPrivateKey(mangled_name, bare_name));
3229
3230 mangled_name = OneByteString::New("foo.name");
3231 bare_name = OneByteString::New("foo.named");
3232 EXPECT(!String::EqualsIgnoringPrivateKey(mangled_name, bare_name));
3233
3234 mangled_name = OneByteString::New("foo.named");
3235 bare_name = OneByteString::New("foo.name");
3236 EXPECT(!String::EqualsIgnoringPrivateKey(mangled_name, bare_name));
3237
3238 // Private match.
3239 mangled_name = OneByteString::New("foo@12345");
3240 bare_name = OneByteString::New("foo");
3241 EXPECT(String::EqualsIgnoringPrivateKey(mangled_name, bare_name));
3242
3243 // Private mismatch.
3244 mangled_name = OneByteString::New("food@12345");
3245 bare_name = OneByteString::New("foo");
3246 EXPECT(!String::EqualsIgnoringPrivateKey(mangled_name, bare_name));
3247
3248 // Private mismatch 2.
3249 mangled_name = OneByteString::New("foo@12345");
3250 bare_name = OneByteString::New("food");
3251 EXPECT(!String::EqualsIgnoringPrivateKey(mangled_name, bare_name));
3252
3253 // Private mixin application match.
3254 mangled_name = OneByteString::New("_M1@12345&_M2@12345&_M3@12345");
3255 bare_name = OneByteString::New("_M1&_M2&_M3");
3256 EXPECT(String::EqualsIgnoringPrivateKey(mangled_name, bare_name));
3257
3258 // Private mixin application mismatch.
3259 mangled_name = OneByteString::New("_M1@12345&_M2@12345&_M3@12345");
3260 bare_name = OneByteString::New("_M1&_M2&_M4");
3261 EXPECT(!String::EqualsIgnoringPrivateKey(mangled_name, bare_name));
3262
3263 // Private constructor match.
3264 mangled_name = OneByteString::New("foo@12345.");
3265 bare_name = OneByteString::New("foo.");
3266 EXPECT(String::EqualsIgnoringPrivateKey(mangled_name, bare_name));
3267
3268 // Private constructor mismatch.
3269 mangled_name = OneByteString::New("foo@12345.");
3270 bare_name = OneByteString::New("foo");
3271 EXPECT(!String::EqualsIgnoringPrivateKey(mangled_name, bare_name));
3272
3273 // Private constructor mismatch 2.
3274 mangled_name = OneByteString::New("foo@12345");
3275 bare_name = OneByteString::New("foo.");
3276 EXPECT(!String::EqualsIgnoringPrivateKey(mangled_name, bare_name));
3277
3278 // Named private constructor match.
3279 mangled_name = OneByteString::New("foo@12345.named");
3280 bare_name = OneByteString::New("foo.named");
3281 EXPECT(String::EqualsIgnoringPrivateKey(mangled_name, bare_name));
3282
3283 // Named private constructor mismatch.
3284 mangled_name = OneByteString::New("foo@12345.name");
3285 bare_name = OneByteString::New("foo.named");
3286 EXPECT(!String::EqualsIgnoringPrivateKey(mangled_name, bare_name));
3287
3288 // Named private constructor mismatch 2.
3289 mangled_name = OneByteString::New("foo@12345.named");
3290 bare_name = OneByteString::New("foo.name");
3291 EXPECT(!String::EqualsIgnoringPrivateKey(mangled_name, bare_name));
3292
3293 // Named double-private constructor match. Yes, this happens.
3294 mangled_name = OneByteString::New("foo@12345.named@12345");
3295 bare_name = OneByteString::New("foo.named");
3296 EXPECT(String::EqualsIgnoringPrivateKey(mangled_name, bare_name));
3297
3298 // Named double-private constructor match where the caller knows the private
3299 // key. Yes, this also happens.
3300 mangled_name = OneByteString::New("foo@12345.named@12345");
3301 bare_name = OneByteString::New("foo@12345.named");
3302 EXPECT(String::EqualsIgnoringPrivateKey(mangled_name, bare_name));
3303
3304 // Named double-private constructor mismatch.
3305 mangled_name = OneByteString::New("foo@12345.name@12345");
3306 bare_name = OneByteString::New("foo.named");
3307 EXPECT(!String::EqualsIgnoringPrivateKey(mangled_name, bare_name));
3308
3309 // Named double-private constructor mismatch.
3310 mangled_name = OneByteString::New("foo@12345.named@12345");
3311 bare_name = OneByteString::New("foo.name");
3312 EXPECT(!String::EqualsIgnoringPrivateKey(mangled_name, bare_name));
3313}
3314
3315ISOLATE_UNIT_TEST_CASE_WITH_EXPECTATION(ArrayNew_Overflow_Crash, "Crash") {
3317}
3318
3319TEST_CASE(StackTraceFormat) {
3320 const char* kScriptChars =
3321 "void baz() {\n"
3322 " throw 'MyException';\n"
3323 "}\n"
3324 "\n"
3325 "class _OtherClass {\n"
3326 " _OtherClass._named() {\n"
3327 " baz();\n"
3328 " }\n"
3329 "}\n"
3330 "\n"
3331 "set globalVar(var value) {\n"
3332 " new _OtherClass._named();\n"
3333 "}\n"
3334 "\n"
3335 "void _bar() {\n"
3336 " globalVar = null;\n"
3337 "}\n"
3338 "\n"
3339 "class MyClass {\n"
3340 " MyClass() {\n"
3341 " (() => foo())();\n"
3342 " }\n"
3343 "\n"
3344 " static get field {\n"
3345 " _bar();\n"
3346 " }\n"
3347 "\n"
3348 " static foo() {\n"
3349 " fooHelper() {\n"
3350 " field;\n"
3351 " }\n"
3352 " fooHelper();\n"
3353 " }\n"
3354 "}\n"
3355 "\n"
3356 "main() {\n"
3357 " (() => new MyClass())();\n"
3358 "}\n";
3359 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
3360 EXPECT_VALID(lib);
3361 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, nullptr);
3362
3363 const char* lib_url = "file:///test-lib";
3364 const size_t kBufferSize = 1024;
3365 char expected[kBufferSize];
3366 snprintf(expected, kBufferSize,
3367 "Unhandled exception:\n"
3368 "MyException\n"
3369 "#0 baz (%1$s:2:3)\n"
3370 "#1 new _OtherClass._named (%1$s:7:5)\n"
3371 "#2 globalVar= (%1$s:12:7)\n"
3372 "#3 _bar (%1$s:16:3)\n"
3373 "#4 MyClass.field (%1$s:25:5)\n"
3374 "#5 MyClass.foo.fooHelper (%1$s:30:7)\n"
3375 "#6 MyClass.foo (%1$s:32:5)\n"
3376 "#7 new MyClass.<anonymous closure> (%1$s:21:12)\n"
3377 "#8 new MyClass (%1$s:21:18)\n"
3378 "#9 main.<anonymous closure> (%1$s:37:14)\n"
3379 "#10 main (%1$s:37:24)",
3380 lib_url);
3381
3382 EXPECT_ERROR(result, expected);
3383}
3384
3385ISOLATE_UNIT_TEST_CASE(WeakProperty_PreserveRecurse) {
3386 // This used to end in an infinite recursion. Caused by scavenging the weak
3387 // property before scavenging the key.
3389 Array& arr = Array::Handle(Array::New(1));
3390 {
3391 HANDLESCOPE(thread);
3393 key ^= OneByteString::New("key");
3394 arr.SetAt(0, key);
3396 value ^= OneByteString::New("value");
3397 weak ^= WeakProperty::New();
3398 weak.set_key(key);
3399 weak.set_value(value);
3400 }
3402 EXPECT(weak.key() != Object::null());
3403 EXPECT(weak.value() != Object::null());
3404}
3405
3406ISOLATE_UNIT_TEST_CASE(WeakProperty_PreserveOne_NewSpace) {
3409 key ^= OneByteString::New("key");
3410 {
3411 HANDLESCOPE(thread);
3413 value ^= OneByteString::New("value");
3414 weak ^= WeakProperty::New();
3415 weak.set_key(key);
3416 weak.set_value(value);
3417 }
3418 GCTestHelper::CollectNewSpace();
3419 EXPECT(weak.key() != Object::null());
3420 EXPECT(weak.value() != Object::null());
3421}
3422
3423ISOLATE_UNIT_TEST_CASE(WeakProperty_PreserveTwo_NewSpace) {
3425 String& key1 = String::Handle();
3426 key1 ^= OneByteString::New("key1");
3428 String& key2 = String::Handle();
3429 key2 ^= OneByteString::New("key2");
3430 {
3431 HANDLESCOPE(thread);
3432 String& value1 = String::Handle();
3433 value1 ^= OneByteString::New("value1");
3435 weak1.set_key(key1);
3436 weak1.set_value(value1);
3437 String& value2 = String::Handle();
3438 value2 ^= OneByteString::New("value2");
3440 weak2.set_key(key2);
3441 weak2.set_value(value2);
3442 }
3443 GCTestHelper::CollectNewSpace();
3444 EXPECT(weak1.key() != Object::null());
3445 EXPECT(weak1.value() != Object::null());
3446 EXPECT(weak2.key() != Object::null());
3447 EXPECT(weak2.value() != Object::null());
3448}
3449
3450ISOLATE_UNIT_TEST_CASE(WeakProperty_PreserveTwoShared_NewSpace) {
3454 key ^= OneByteString::New("key");
3455 {
3456 HANDLESCOPE(thread);
3457 String& value1 = String::Handle();
3458 value1 ^= OneByteString::New("value1");
3460 weak1.set_key(key);
3461 weak1.set_value(value1);
3462 String& value2 = String::Handle();
3463 value2 ^= OneByteString::New("value2");
3465 weak2.set_key(key);
3466 weak2.set_value(value2);
3467 }
3468 GCTestHelper::CollectNewSpace();
3469 EXPECT(weak1.key() != Object::null());
3470 EXPECT(weak1.value() != Object::null());
3471 EXPECT(weak2.key() != Object::null());
3472 EXPECT(weak2.value() != Object::null());
3473}
3474
3475ISOLATE_UNIT_TEST_CASE(WeakProperty_PreserveOne_OldSpace) {
3479 {
3480 HANDLESCOPE(thread);
3482 value ^= OneByteString::New("value", Heap::kOld);
3484 weak.set_key(key);
3485 weak.set_value(value);
3486 }
3488 EXPECT(weak.key() != Object::null());
3489 EXPECT(weak.value() != Object::null());
3490}
3491
3492ISOLATE_UNIT_TEST_CASE(WeakProperty_PreserveTwo_OldSpace) {
3494 String& key1 = String::Handle();
3495 key1 ^= OneByteString::New("key1", Heap::kOld);
3497 String& key2 = String::Handle();
3498 key2 ^= OneByteString::New("key2", Heap::kOld);
3499 {
3500 HANDLESCOPE(thread);
3501 String& value1 = String::Handle();
3502 value1 ^= OneByteString::New("value1", Heap::kOld);
3504 weak1.set_key(key1);
3505 weak1.set_value(value1);
3506 String& value2 = String::Handle();
3507 value2 ^= OneByteString::New("value2", Heap::kOld);
3509 weak2.set_key(key2);
3510 weak2.set_value(value2);
3511 }
3513 EXPECT(weak1.key() != Object::null());
3514 EXPECT(weak1.value() != Object::null());
3515 EXPECT(weak2.key() != Object::null());
3516 EXPECT(weak2.value() != Object::null());
3517}
3518
3519ISOLATE_UNIT_TEST_CASE(WeakProperty_PreserveTwoShared_OldSpace) {
3524 {
3525 HANDLESCOPE(thread);
3526 String& value1 = String::Handle();
3527 value1 ^= OneByteString::New("value1", Heap::kOld);
3529 weak1.set_key(key);
3530 weak1.set_value(value1);
3531 String& value2 = String::Handle();
3532 value2 ^= OneByteString::New("value2", Heap::kOld);
3534 weak2.set_key(key);
3535 weak2.set_value(value2);
3536 }
3538 EXPECT(weak1.key() != Object::null());
3539 EXPECT(weak1.value() != Object::null());
3540 EXPECT(weak2.key() != Object::null());
3541 EXPECT(weak2.value() != Object::null());
3542}
3543
3544ISOLATE_UNIT_TEST_CASE(WeakProperty_ClearOne_NewSpace) {
3546 {
3547 HANDLESCOPE(thread);
3549 key ^= OneByteString::New("key");
3551 value ^= OneByteString::New("value");
3552 weak ^= WeakProperty::New();
3553 weak.set_key(key);
3554 weak.set_value(value);
3557 }
3558 GCTestHelper::CollectNewSpace();
3559 EXPECT(weak.key() == Object::null());
3560 EXPECT(weak.value() == Object::null());
3561}
3562
3563ISOLATE_UNIT_TEST_CASE(WeakProperty_ClearTwoShared_NewSpace) {
3566 {
3567 HANDLESCOPE(thread);
3569 key ^= OneByteString::New("key");
3570 String& value1 = String::Handle();
3571 value1 ^= OneByteString::New("value1");
3573 weak1.set_key(key);
3574 weak1.set_value(value1);
3575 String& value2 = String::Handle();
3576 value2 ^= OneByteString::New("value2");
3578 weak2.set_key(key);
3579 weak2.set_value(value2);
3580 }
3581 GCTestHelper::CollectNewSpace();
3582 EXPECT(weak1.key() == Object::null());
3583 EXPECT(weak1.value() == Object::null());
3584 EXPECT(weak2.key() == Object::null());
3585 EXPECT(weak2.value() == Object::null());
3586}
3587
3588ISOLATE_UNIT_TEST_CASE(WeakProperty_ClearOne_OldSpace) {
3590 {
3591 HANDLESCOPE(thread);
3595 value ^= OneByteString::New("value", Heap::kOld);
3597 weak.set_key(key);
3598 weak.set_value(value);
3601 }
3603 EXPECT(weak.key() == Object::null());
3604 EXPECT(weak.value() == Object::null());
3605}
3606
3607ISOLATE_UNIT_TEST_CASE(WeakProperty_ClearTwoShared_OldSpace) {
3610 {
3611 HANDLESCOPE(thread);
3614 String& value1 = String::Handle();
3615 value1 ^= OneByteString::New("value1");
3617 weak1.set_key(key);
3618 weak1.set_value(value1);
3619 String& value2 = String::Handle();
3620 value2 ^= OneByteString::New("value2", Heap::kOld);
3622 weak2.set_key(key);
3623 weak2.set_value(value2);
3624 }
3626 EXPECT(weak1.key() == Object::null());
3627 EXPECT(weak1.value() == Object::null());
3628 EXPECT(weak2.key() == Object::null());
3629 EXPECT(weak2.value() == Object::null());
3630}
3631
3632static void WeakReference_PreserveOne(Thread* thread, Heap::Space space) {
3633 auto& weak = WeakReference::Handle();
3634 const auto& target = String::Handle(OneByteString::New("target", space));
3635 {
3636 HANDLESCOPE(thread);
3637 ObjectStore* object_store = thread->isolate_group()->object_store();
3638 const auto& type_arguments =
3639 TypeArguments::Handle(object_store->type_argument_double());
3640 weak ^= WeakReference::New(space);
3641 weak.set_target(target);
3642 weak.SetTypeArguments(type_arguments);
3643 }
3644
3645 if (space == Heap::kNew) {
3646 GCTestHelper::CollectNewSpace();
3647 } else {
3649 }
3650
3651 EXPECT(weak.target() != Object::null());
3652 EXPECT(weak.GetTypeArguments() != Object::null());
3653}
3654
3655ISOLATE_UNIT_TEST_CASE(WeakReference_PreserveOne_NewSpace) {
3657}
3658
3659ISOLATE_UNIT_TEST_CASE(WeakReference_PreserveOne_OldSpace) {
3661}
3662
3663static void WeakReference_ClearOne(Thread* thread, Heap::Space space) {
3664 auto& weak = WeakReference::Handle();
3665 {
3666 HANDLESCOPE(thread);
3667 const auto& target = String::Handle(OneByteString::New("target", space));
3668 ObjectStore* object_store = thread->isolate_group()->object_store();
3669 const auto& type_arguments =
3670 TypeArguments::Handle(object_store->type_argument_double());
3671 weak ^= WeakReference::New(space);
3672 weak.set_target(target);
3673 weak.SetTypeArguments(type_arguments);
3674 }
3675
3676 if (space == Heap::kNew) {
3677 GCTestHelper::CollectNewSpace();
3678 } else {
3680 }
3681
3682 EXPECT(weak.target() == Object::null());
3683 EXPECT(weak.GetTypeArguments() != Object::null());
3684}
3685
3686ISOLATE_UNIT_TEST_CASE(WeakReference_ClearOne_NewSpace) {
3688}
3689
3690ISOLATE_UNIT_TEST_CASE(WeakReference_ClearOne_OldSpace) {
3692}
3693
3695 Thread* thread,
3696 Heap::Space space) {
3697 auto& weak_property = WeakProperty::Handle();
3698 const auto& key = String::Handle(OneByteString::New("key", space));
3699 {
3700 HANDLESCOPE(thread);
3701 ObjectStore* object_store = thread->isolate_group()->object_store();
3702 const auto& type_arguments =
3703 TypeArguments::Handle(object_store->type_argument_double());
3704 const auto& weak_reference =
3706 const auto& target = String::Handle(OneByteString::New("target", space));
3707 weak_reference.set_target(target);
3708 weak_reference.SetTypeArguments(type_arguments);
3709
3710 weak_property ^= WeakProperty::New(space);
3711 weak_property.set_key(key);
3712 weak_property.set_value(weak_reference);
3713 }
3714
3715 if (space == Heap::kNew) {
3716 GCTestHelper::CollectNewSpace();
3717 } else {
3719 }
3720
3721 const auto& weak_reference =
3722 WeakReference::CheckedHandle(Z, weak_property.value());
3723 EXPECT(weak_reference.target() == Object::null());
3724 EXPECT(weak_reference.GetTypeArguments() != Object::null());
3725}
3726
3728 WeakReference_Clear_ReachableThroughWeakProperty_NewSpace) {
3730}
3731
3733 WeakReference_Clear_ReachableThroughWeakProperty_OldSpace) {
3735}
3736
3738 Thread* thread,
3739 Heap::Space space) {
3740 auto& weak_property = WeakProperty::Handle();
3741 const auto& key = String::Handle(OneByteString::New("key", space));
3742 const auto& target = String::Handle(OneByteString::New("target", space));
3743 {
3744 HANDLESCOPE(thread);
3745 ObjectStore* object_store = thread->isolate_group()->object_store();
3746 const auto& type_arguments =
3747 TypeArguments::Handle(object_store->type_argument_double());
3748 const auto& weak_reference =
3750 weak_reference.set_target(target);
3751 weak_reference.SetTypeArguments(type_arguments);
3752
3753 weak_property ^= WeakProperty::New(space);
3754 weak_property.set_key(key);
3755 weak_property.set_value(weak_reference);
3756 }
3757
3758 if (space == Heap::kNew) {
3759 GCTestHelper::CollectNewSpace();
3760 } else {
3762 }
3763
3764 const auto& weak_reference =
3765 WeakReference::CheckedHandle(Z, weak_property.value());
3766 EXPECT(weak_reference.target() != Object::null());
3767 EXPECT(weak_reference.GetTypeArguments() != Object::null());
3768}
3769
3771 WeakReference_Preserve_ReachableThroughWeakProperty_NewSpace) {
3773}
3774
3776 WeakReference_Preserve_ReachableThroughWeakProperty_OldSpace) {
3778}
3779
3782 Object& target0 = Object::Handle();
3783 {
3784 HANDLESCOPE(thread);
3785 target0 = String::New("0", Heap::kNew);
3786 Object& target1 = Object::Handle(String::New("1", Heap::kNew));
3787 array.SetAt(0, target0);
3788 array.SetAt(1, target1);
3789 }
3790
3791 EXPECT(array.Length() == 2);
3792 EXPECT(array.At(0) != Object::null());
3793 EXPECT(array.At(1) != Object::null());
3794
3795 GCTestHelper::CollectNewSpace();
3796
3797 EXPECT(array.Length() == 2);
3798 EXPECT(array.At(0) != Object::null()); // Survives
3799 EXPECT(array.At(1) == Object::null()); // Cleared
3800}
3801
3804 Object& target0 = Object::Handle();
3805 {
3806 HANDLESCOPE(thread);
3807 target0 = String::New("0", Heap::kOld);
3808 Object& target1 = Object::Handle(String::New("1", Heap::kOld));
3809 array.SetAt(0, target0);
3810 array.SetAt(1, target1);
3811 }
3812
3813 EXPECT(array.Length() == 2);
3814 EXPECT(array.At(0) != Object::null());
3815 EXPECT(array.At(1) != Object::null());
3816
3818
3819 EXPECT(array.Length() == 2);
3820 EXPECT(array.At(0) != Object::null()); // Survives
3821 EXPECT(array.At(1) == Object::null()); // Cleared
3822}
3823
3824static int NumEntries(const FinalizerEntry& entry, intptr_t acc = 0) {
3825 if (entry.IsNull()) {
3826 return acc;
3827 }
3828 return NumEntries(FinalizerEntry::Handle(entry.next()), acc + 1);
3829}
3830
3831static void Finalizer_PreserveOne(Thread* thread,
3832 Heap::Space space,
3833 bool with_detach) {
3834#ifdef DEBUG
3835 SetFlagScope<bool> sfs(&FLAG_trace_finalizers, true);
3836#endif
3837
3838 MessageHandler* handler = thread->isolate()->message_handler();
3839 {
3841 EXPECT_EQ(0, aq.queue()->Length());
3842 }
3843
3844 const auto& finalizer = Finalizer::Handle(Finalizer::New(space));
3845 finalizer.set_isolate(thread->isolate());
3846 const auto& entry =
3848 const auto& value = String::Handle(OneByteString::New("value", space));
3849 entry.set_value(value);
3850 auto& detach = Object::Handle();
3851 if (with_detach) {
3852 detach = OneByteString::New("detach", space);
3853 } else {
3854 detach = Object::null();
3855 }
3856 entry.set_detach(detach);
3857 const auto& token = String::Handle(OneByteString::New("token", space));
3858 entry.set_token(token);
3859
3860 if (space == Heap::kNew) {
3861 GCTestHelper::CollectNewSpace();
3862 } else {
3864 }
3865
3866 // Nothing in the entry should have been collected.
3867 EXPECT_NE(Object::null(), entry.value());
3868 EXPECT((entry.detach() == Object::null()) ^ with_detach);
3869 EXPECT_NE(Object::null(), entry.token());
3870
3871 // The entry should not have moved to the collected list.
3872 EXPECT_EQ(0,
3873 NumEntries(FinalizerEntry::Handle(finalizer.entries_collected())));
3874
3875 // We should have no messages.
3876 {
3877 // Acquire ownership of message handler queues.
3879 EXPECT_EQ(0, aq.queue()->Length());
3880 }
3881}
3882
3883ISOLATE_UNIT_TEST_CASE(Finalizer_PreserveNoDetachOne_NewSpace) {
3884 Finalizer_PreserveOne(thread, Heap::kNew, false);
3885}
3886
3887ISOLATE_UNIT_TEST_CASE(Finalizer_PreserveNoDetachOne_OldSpace) {
3888 Finalizer_PreserveOne(thread, Heap::kOld, false);
3889}
3890
3891ISOLATE_UNIT_TEST_CASE(Finalizer_PreserveWithDetachOne_NewSpace) {
3892 Finalizer_PreserveOne(thread, Heap::kNew, true);
3893}
3894
3895ISOLATE_UNIT_TEST_CASE(Finalizer_PreserveWithDetachOne_OldSpace) {
3896 Finalizer_PreserveOne(thread, Heap::kOld, true);
3897}
3898
3899static void Finalizer_ClearDetachOne(Thread* thread, Heap::Space space) {
3900#ifdef DEBUG
3901 SetFlagScope<bool> sfs(&FLAG_trace_finalizers, true);
3902#endif
3903
3904 MessageHandler* handler = thread->isolate()->message_handler();
3905 {
3907 EXPECT_EQ(0, aq.queue()->Length());
3908 }
3909
3910 const auto& finalizer = Finalizer::Handle(Finalizer::New(space));
3911 finalizer.set_isolate(thread->isolate());
3912 const auto& entry =
3914 const auto& value = String::Handle(OneByteString::New("value", space));
3915 entry.set_value(value);
3916 const auto& token = String::Handle(OneByteString::New("token", space));
3917 entry.set_token(token);
3918
3919 {
3920 HANDLESCOPE(thread);
3921 const auto& detach = String::Handle(OneByteString::New("detach", space));
3922 entry.set_detach(detach);
3923 }
3924
3925 if (space == Heap::kNew) {
3926 GCTestHelper::CollectNewSpace();
3927 } else {
3929 }
3930
3931 // Detach should have been collected.
3932 EXPECT_NE(Object::null(), entry.value());
3933 EXPECT_EQ(Object::null(), entry.detach());
3934 EXPECT_NE(Object::null(), entry.token());
3935
3936 // The entry should not have moved to the collected list.
3937 EXPECT_EQ(0,
3938 NumEntries(FinalizerEntry::Handle(finalizer.entries_collected())));
3939
3940 // We should have no messages.
3941 {
3942 // Acquire ownership of message handler queues.
3944 EXPECT_EQ(0, aq.queue()->Length());
3945 }
3946}
3947
3948ISOLATE_UNIT_TEST_CASE(Finalizer_ClearDetachOne_NewSpace) {
3950}
3951
3952ISOLATE_UNIT_TEST_CASE(Finalizer_ClearDetachOne_OldSpace) {
3954}
3955
3957 Heap::Space space,
3958 bool null_token) {
3959#ifdef DEBUG
3960 SetFlagScope<bool> sfs(&FLAG_trace_finalizers, true);
3961#endif
3962
3963 MessageHandler* handler = thread->isolate()->message_handler();
3964 {
3966 EXPECT_EQ(0, aq.queue()->Length());
3967 }
3968
3969 const auto& finalizer = Finalizer::Handle(Finalizer::New(space));
3970 finalizer.set_isolate(thread->isolate());
3971 const auto& entry =
3973 const auto& detach = String::Handle(OneByteString::New("detach", space));
3974 auto& token = Object::Handle();
3975 if (null_token) {
3976 // Null is a valid token in Dart finalizers.
3977 token = Object::null();
3978 } else {
3979 token = OneByteString::New("token", space);
3980 }
3981 entry.set_token(token);
3982 entry.set_detach(detach);
3983
3984 {
3985 HANDLESCOPE(thread);
3986 const auto& value = String::Handle(OneByteString::New("value", space));
3987 entry.set_value(value);
3988 }
3989
3990 if (space == Heap::kNew) {
3991 GCTestHelper::CollectNewSpace();
3992 } else {
3994 }
3995
3996 // Value should have been collected.
3997 EXPECT_EQ(Object::null(), entry.value());
3998 EXPECT_NE(Object::null(), entry.detach());
3999
4000 // The entry should have moved to the collected list.
4001 EXPECT_EQ(1,
4002 NumEntries(FinalizerEntry::Handle(finalizer.entries_collected())));
4003
4004 // We should have 1 message.
4005 {
4006 // Acquire ownership of message handler queues.
4008 EXPECT_EQ(1, aq.queue()->Length());
4009 }
4010}
4011
4012ISOLATE_UNIT_TEST_CASE(Finalizer_ClearValueOne_NewSpace) {
4013 Finalizer_ClearValueOne(thread, Heap::kNew, false);
4014}
4015
4016ISOLATE_UNIT_TEST_CASE(Finalizer_ClearValueOne_OldSpace) {
4017 Finalizer_ClearValueOne(thread, Heap::kOld, false);
4018}
4019
4020ISOLATE_UNIT_TEST_CASE(Finalizer_ClearValueNullTokenOne_NewSpace) {
4021 Finalizer_ClearValueOne(thread, Heap::kNew, true);
4022}
4023
4024ISOLATE_UNIT_TEST_CASE(Finalizer_ClearValueNullTokenOne_OldSpace) {
4025 Finalizer_ClearValueOne(thread, Heap::kOld, true);
4026}
4027
4028static void Finalizer_DetachOne(Thread* thread,
4029 Heap::Space space,
4030 bool clear_value) {
4031#ifdef DEBUG
4032 SetFlagScope<bool> sfs(&FLAG_trace_finalizers, true);
4033#endif
4034
4035 MessageHandler* handler = thread->isolate()->message_handler();
4036 {
4038 EXPECT_EQ(0, aq.queue()->Length());
4039 }
4040
4041 const auto& finalizer = Finalizer::Handle(Finalizer::New(space));
4042 finalizer.set_isolate(thread->isolate());
4043 const auto& entry =
4045 const auto& detach = String::Handle(OneByteString::New("detach", space));
4046 entry.set_detach(detach);
4047
4048 // Simulate calling detach, setting the token of the entry to the entry.
4049 entry.set_token(entry);
4050
4051 auto& value = String::Handle();
4052 {
4053 HANDLESCOPE(thread);
4054
4055 const auto& object = String::Handle(OneByteString::New("value", space));
4056 entry.set_value(object);
4057 if (!clear_value) {
4058 value = object.ptr();
4059 }
4060 }
4061
4062 if (space == Heap::kNew) {
4063 GCTestHelper::CollectNewSpace();
4064 } else {
4066 }
4067
4068 EXPECT((entry.value() == Object::null()) ^ !clear_value);
4069 EXPECT_NE(Object::null(), entry.detach());
4070 EXPECT_EQ(entry.ptr(), entry.token());
4071
4072 // The entry should have been removed entirely
4073 EXPECT_EQ(0,
4074 NumEntries(FinalizerEntry::Handle(finalizer.entries_collected())));
4075
4076 // We should have no message.
4077 {
4078 // Acquire ownership of message handler queues.
4080 EXPECT_EQ(0, aq.queue()->Length());
4081 }
4082}
4083
4084ISOLATE_UNIT_TEST_CASE(Finalizer_DetachOne_NewSpace) {
4085 Finalizer_DetachOne(thread, Heap::kNew, false);
4086}
4087
4088ISOLATE_UNIT_TEST_CASE(Finalizer_DetachOne_OldSpace) {
4089 Finalizer_DetachOne(thread, Heap::kOld, false);
4090}
4091
4092ISOLATE_UNIT_TEST_CASE(Finalizer_DetachAndClearValueOne_NewSpace) {
4093 Finalizer_DetachOne(thread, Heap::kNew, true);
4094}
4095
4096ISOLATE_UNIT_TEST_CASE(Finalizer_DetachAndClearValueOne_OldSpace) {
4097 Finalizer_DetachOne(thread, Heap::kOld, true);
4098}
4099
4100static void Finalizer_GcFinalizer(Thread* thread, Heap::Space space) {
4101#ifdef DEBUG
4102 SetFlagScope<bool> sfs(&FLAG_trace_finalizers, true);
4103#endif
4104
4105 MessageHandler* handler = thread->isolate()->message_handler();
4106 {
4108 EXPECT_EQ(0, aq.queue()->Length());
4109 }
4110
4111 const auto& detach = String::Handle(OneByteString::New("detach", space));
4112 const auto& token = String::Handle(OneByteString::New("token", space));
4113
4114 {
4115 HANDLESCOPE(thread);
4116 const auto& finalizer = Finalizer::Handle(Finalizer::New(space));
4117 finalizer.set_isolate(thread->isolate());
4118 const auto& entry =
4120 entry.set_detach(detach);
4121 entry.set_token(token);
4122 const auto& value = String::Handle(OneByteString::New("value", space));
4123 entry.set_value(value);
4124 }
4125
4126 if (space == Heap::kNew) {
4127 GCTestHelper::CollectNewSpace();
4128 } else {
4130 }
4131
4132 // We should have no message, the Finalizer itself has been GCed.
4133 {
4134 // Acquire ownership of message handler queues.
4136 EXPECT_EQ(0, aq.queue()->Length());
4137 }
4138}
4139
4140ISOLATE_UNIT_TEST_CASE(Finalizer_GcFinalizer_NewSpace) {
4142}
4143
4144ISOLATE_UNIT_TEST_CASE(Finalizer_GcFinalizer_OldSpace) {
4146}
4147
4149 Thread* thread,
4150 Heap::Space* spaces,
4151 bool collect_old_space,
4152 bool collect_new_space,
4153 bool evacuate_new_space_and_collect_old_space,
4154 bool clear_value_1,
4155 bool clear_value_2,
4156 bool clear_detach_1,
4157 bool clear_detach_2) {
4158#ifdef DEBUG
4159 SetFlagScope<bool> sfs(&FLAG_trace_finalizers, true);
4160#endif
4161
4162 MessageHandler* handler = thread->isolate()->message_handler();
4163 // We're reusing the isolate in a loop, so there are messages from previous
4164 // runs of this test.
4165 intptr_t queue_length_start = 0;
4166 {
4168 queue_length_start = aq.queue()->Length();
4169 }
4170
4171 const auto& finalizer = Finalizer::Handle(Finalizer::New(spaces[0]));
4172 finalizer.set_isolate(thread->isolate());
4173 const auto& entry1 =
4174 FinalizerEntry::Handle(FinalizerEntry::New(finalizer, spaces[1]));
4175 const auto& entry2 =
4176 FinalizerEntry::Handle(FinalizerEntry::New(finalizer, spaces[2]));
4177
4178 auto& value1 = String::Handle();
4179 auto& detach1 = String::Handle();
4180 const auto& token1 = String::Handle(OneByteString::New("token1", spaces[3]));
4181 entry1.set_token(token1);
4182
4183 auto& value2 = String::Handle();
4184 auto& detach2 = String::Handle();
4185 const auto& token2 = String::Handle(OneByteString::New("token2", spaces[4]));
4186 entry2.set_token(token2);
4187 entry2.set_detach(detach2);
4188
4189 {
4190 HANDLESCOPE(thread);
4191 auto& object = String::Handle();
4192
4193 object ^= OneByteString::New("value1", spaces[5]);
4194 entry1.set_value(object);
4195 if (!clear_value_1) {
4196 value1 = object.ptr();
4197 }
4198
4199 object ^= OneByteString::New("detach", spaces[6]);
4200 entry1.set_detach(object);
4201 if (!clear_detach_1) {
4202 detach1 = object.ptr();
4203 }
4204
4205 object ^= OneByteString::New("value2", spaces[7]);
4206 entry2.set_value(object);
4207 if (!clear_value_2) {
4208 value2 = object.ptr();
4209 }
4210
4211 object ^= OneByteString::New("detach", spaces[8]);
4212 entry2.set_detach(object);
4213 if (!clear_detach_2) {
4214 detach2 = object.ptr();
4215 }
4216 }
4217
4218 if (collect_old_space) {
4219 GCTestHelper::CollectOldSpace();
4220 }
4221 if (collect_new_space) {
4222 GCTestHelper::CollectNewSpace();
4223 }
4224 if (evacuate_new_space_and_collect_old_space) {
4226 }
4227
4228 EXPECT((entry1.value() == Object::null()) ^ !clear_value_1);
4229 EXPECT((entry2.value() == Object::null()) ^ !clear_value_2);
4230 EXPECT((entry1.detach() == Object::null()) ^ !clear_detach_1);
4231 EXPECT((entry2.detach() == Object::null()) ^ !clear_detach_2);
4232 EXPECT_NE(Object::null(), entry1.token());
4233 EXPECT_NE(Object::null(), entry2.token());
4234
4235 const intptr_t expect_num_cleared =
4236 (clear_value_1 ? 1 : 0) + (clear_value_2 ? 1 : 0);
4237 EXPECT_EQ(expect_num_cleared,
4238 NumEntries(FinalizerEntry::Handle(finalizer.entries_collected())));
4239
4240 const intptr_t expect_num_messages = expect_num_cleared == 0 ? 0 : 1;
4241 {
4242 // Acquire ownership of message handler queues.
4244 EXPECT_EQ(expect_num_messages + queue_length_start, aq.queue()->Length());
4245 }
4246}
4247
4249
4250static void Finalizer_TwoEntries(Thread* thread,
4251 Heap::Space space,
4252 bool clear_value_1,
4253 bool clear_value_2,
4254 bool clear_detach_1,
4255 bool clear_detach_2) {
4256 const bool collect_old_space = true;
4257 const bool collect_new_space = space == Heap::kNew;
4258 const bool evacuate_new_space_and_collect_old_space = !collect_new_space;
4259
4261 for (intptr_t i = 0; i < kFinalizerTwoEntriesNumObjects; i++) {
4262 spaces[i] = space;
4263 }
4265 thread, spaces, collect_old_space, collect_new_space,
4266 evacuate_new_space_and_collect_old_space, clear_value_1, clear_value_2,
4267 clear_detach_1, clear_detach_2);
4268}
4269
4270ISOLATE_UNIT_TEST_CASE(Finalizer_ClearValueTwo_NewSpace) {
4271 Finalizer_TwoEntries(thread, Heap::kNew, true, true, false, false);
4272}
4273
4274ISOLATE_UNIT_TEST_CASE(Finalizer_ClearValueTwo_OldSpace) {
4275 Finalizer_TwoEntries(thread, Heap::kOld, true, true, false, false);
4276}
4277
4278ISOLATE_UNIT_TEST_CASE(Finalizer_ClearFirstValue_NewSpace) {
4279 Finalizer_TwoEntries(thread, Heap::kNew, true, false, false, false);
4280}
4281
4282ISOLATE_UNIT_TEST_CASE(Finalizer_ClearFirstValue_OldSpace) {
4283 Finalizer_TwoEntries(thread, Heap::kOld, true, false, false, false);
4284}
4285
4286ISOLATE_UNIT_TEST_CASE(Finalizer_ClearSecondValue_NewSpace) {
4287 Finalizer_TwoEntries(thread, Heap::kNew, false, true, false, false);
4288}
4289
4290ISOLATE_UNIT_TEST_CASE(Finalizer_ClearSecondValue_OldSpace) {
4291 Finalizer_TwoEntries(thread, Heap::kOld, false, true, false, false);
4292}
4293
4294ISOLATE_UNIT_TEST_CASE(Finalizer_PreserveTwo_NewSpace) {
4295 Finalizer_TwoEntries(thread, Heap::kNew, false, false, false, false);
4296}
4297
4298ISOLATE_UNIT_TEST_CASE(Finalizer_PreserveTwo_OldSpace) {
4299 Finalizer_TwoEntries(thread, Heap::kOld, false, false, false, false);
4300}
4301
4302ISOLATE_UNIT_TEST_CASE(Finalizer_ClearDetachTwo_NewSpace) {
4303 Finalizer_TwoEntries(thread, Heap::kNew, false, false, true, true);
4304}
4305
4306ISOLATE_UNIT_TEST_CASE(Finalizer_ClearDetachTwo_OldSpace) {
4307 Finalizer_TwoEntries(thread, Heap::kOld, false, false, true, true);
4308}
4309
4310static void Finalizer_TwoEntriesCrossGen(Thread* thread, intptr_t test_i) {
4311 ASSERT(test_i < (1 << kFinalizerTwoEntriesNumObjects));
4313 for (intptr_t i = 0; i < kFinalizerTwoEntriesNumObjects; i++) {
4314 spaces[i] = ((test_i >> i) & 0x1) == 0x1 ? Heap::kOld : Heap::kNew;
4315 }
4316 // Either collect or evacuate new space.
4317 for (const bool collect_new_space : {false, true}) {
4318 // Always run old space collection first.
4319 const bool collect_old_space = true;
4320 // Always run old space collection after new space.
4321 const bool evacuate_new_space_and_collect_old_space = true;
4322 for (intptr_t test_j = 0; test_j < 16; test_j++) {
4323 const bool clear_value_1 = (test_j >> 0 & 0x1) == 0x1;
4324 const bool clear_value_2 = (test_j >> 1 & 0x1) == 0x1;
4325 const bool clear_detach_1 = (test_j >> 2 & 0x1) == 0x1;
4326 const bool clear_detach_2 = (test_j >> 3 & 0x1) == 0x1;
4328 thread, spaces, collect_old_space, collect_new_space,
4329 evacuate_new_space_and_collect_old_space, clear_value_1,
4330 clear_value_2, clear_detach_1, clear_detach_2);
4331 }
4332 }
4333}
4334#define FINALIZER_CROSS_GEN_TEST_CASE(n) \
4335 ISOLATE_UNIT_TEST_CASE(Finalizer_CrossGen_##n) { \
4336 Finalizer_TwoEntriesCrossGen(thread, n); \
4337 }
4338
4339#define REPEAT_512(V) \
4340 V(0) \
4341 V(1) \
4342 V(2) \
4343 V(3) \
4344 V(4) \
4345 V(5) \
4346 V(6) \
4347 V(7) \
4348 V(8) \
4349 V(9) \
4350 V(10) \
4351 V(11) \
4352 V(12) \
4353 V(13) \
4354 V(14) \
4355 V(15) \
4356 V(16) \
4357 V(17) \
4358 V(18) \
4359 V(19) \
4360 V(20) \
4361 V(21) \
4362 V(22) \
4363 V(23) \
4364 V(24) \
4365 V(25) \
4366 V(26) \
4367 V(27) \
4368 V(28) \
4369 V(29) \
4370 V(30) \
4371 V(31) \
4372 V(32) \
4373 V(33) \
4374 V(34) \
4375 V(35) \
4376 V(36) \
4377 V(37) \
4378 V(38) \
4379 V(39) \
4380 V(40) \
4381 V(41) \
4382 V(42) \
4383 V(43) \
4384 V(44) \
4385 V(45) \
4386 V(46) \
4387 V(47) \
4388 V(48) \
4389 V(49) \
4390 V(50) \
4391 V(51) \
4392 V(52) \
4393 V(53) \
4394 V(54) \
4395 V(55) \
4396 V(56) \
4397 V(57) \
4398 V(58) \
4399 V(59) \
4400 V(60) \
4401 V(61) \
4402 V(62) \
4403 V(63) \
4404 V(64) \
4405 V(65) \
4406 V(66) \
4407 V(67) \
4408 V(68) \
4409 V(69) \
4410 V(70) \
4411 V(71) \
4412 V(72) \
4413 V(73) \
4414 V(74) \
4415 V(75) \
4416 V(76) \
4417 V(77) \
4418 V(78) \
4419 V(79) \
4420 V(80) \
4421 V(81) \
4422 V(82) \
4423 V(83) \
4424 V(84) \
4425 V(85) \
4426 V(86) \
4427 V(87) \
4428 V(88) \
4429 V(89) \
4430 V(90) \
4431 V(91) \
4432 V(92) \
4433 V(93) \
4434 V(94) \
4435 V(95) \
4436 V(96) \
4437 V(97) \
4438 V(98) \
4439 V(99) \
4440 V(100) \
4441 V(101) \
4442 V(102) \
4443 V(103) \
4444 V(104) \
4445 V(105) \
4446 V(106) \
4447 V(107) \
4448 V(108) \
4449 V(109) \
4450 V(110) \
4451 V(111) \
4452 V(112) \
4453 V(113) \
4454 V(114) \
4455 V(115) \
4456 V(116) \
4457 V(117) \
4458 V(118) \
4459 V(119) \
4460 V(120) \
4461 V(121) \
4462 V(122) \
4463 V(123) \
4464 V(124) \
4465 V(125) \
4466 V(126) \
4467 V(127) \
4468 V(128) \
4469 V(129) \
4470 V(130) \
4471 V(131) \
4472 V(132) \
4473 V(133) \
4474 V(134) \
4475 V(135) \
4476 V(136) \
4477 V(137) \
4478 V(138) \
4479 V(139) \
4480 V(140) \
4481 V(141) \
4482 V(142) \
4483 V(143) \
4484 V(144) \
4485 V(145) \
4486 V(146) \
4487 V(147) \
4488 V(148) \
4489 V(149) \
4490 V(150) \
4491 V(151) \
4492 V(152) \
4493 V(153) \
4494 V(154) \
4495 V(155) \
4496 V(156) \
4497 V(157) \
4498 V(158) \
4499 V(159) \
4500 V(160) \
4501 V(161) \
4502 V(162) \
4503 V(163) \
4504 V(164) \
4505 V(165) \
4506 V(166) \
4507 V(167) \
4508 V(168) \
4509 V(169) \
4510 V(170) \
4511 V(171) \
4512 V(172) \
4513 V(173) \
4514 V(174) \
4515 V(175) \
4516 V(176) \
4517 V(177) \
4518 V(178) \
4519 V(179) \
4520 V(180) \
4521 V(181) \
4522 V(182) \
4523 V(183) \
4524 V(184) \
4525 V(185) \
4526 V(186) \
4527 V(187) \
4528 V(188) \
4529 V(189) \
4530 V(190) \
4531 V(191) \
4532 V(192) \
4533 V(193) \
4534 V(194) \
4535 V(195) \
4536 V(196) \
4537 V(197) \
4538 V(198) \
4539 V(199) \
4540 V(200) \
4541 V(201) \
4542 V(202) \
4543 V(203) \
4544 V(204) \
4545 V(205) \
4546 V(206) \
4547 V(207) \
4548 V(208) \
4549 V(209) \
4550 V(210) \
4551 V(211) \
4552 V(212) \
4553 V(213) \
4554 V(214) \
4555 V(215) \
4556 V(216) \
4557 V(217) \
4558 V(218) \
4559 V(219) \
4560 V(220) \
4561 V(221) \
4562 V(222) \
4563 V(223) \
4564 V(224) \
4565 V(225) \
4566 V(226) \
4567 V(227) \
4568 V(228) \
4569 V(229) \
4570 V(230) \
4571 V(231) \
4572 V(232) \
4573 V(233) \
4574 V(234) \
4575 V(235) \
4576 V(236) \
4577 V(237) \
4578 V(238) \
4579 V(239) \
4580 V(240) \
4581 V(241) \
4582 V(242) \
4583 V(243) \
4584 V(244) \
4585 V(245) \
4586 V(246) \
4587 V(247) \
4588 V(248) \
4589 V(249) \
4590 V(250) \
4591 V(251) \
4592 V(252) \
4593 V(253) \
4594 V(254) \
4595 V(255) \
4596 V(256) \
4597 V(257) \
4598 V(258) \
4599 V(259) \
4600 V(260) \
4601 V(261) \
4602 V(262) \
4603 V(263) \
4604 V(264) \
4605 V(265) \
4606 V(266) \
4607 V(267) \
4608 V(268) \
4609 V(269) \
4610 V(270) \
4611 V(271) \
4612 V(272) \
4613 V(273) \
4614 V(274) \
4615 V(275) \
4616 V(276) \
4617 V(277) \
4618 V(278) \
4619 V(279) \
4620 V(280) \
4621 V(281) \
4622 V(282) \
4623 V(283) \
4624 V(284) \
4625 V(285) \
4626 V(286) \
4627 V(287) \
4628 V(288) \
4629 V(289) \
4630 V(290) \
4631 V(291) \
4632 V(292) \
4633 V(293) \
4634 V(294) \
4635 V(295) \
4636 V(296) \
4637 V(297) \
4638 V(298) \
4639 V(299) \
4640 V(300) \
4641 V(301) \
4642 V(302) \
4643 V(303) \
4644 V(304) \
4645 V(305) \
4646 V(306) \
4647 V(307) \
4648 V(308) \
4649 V(309) \
4650 V(310) \
4651 V(311) \
4652 V(312) \
4653 V(313) \
4654 V(314) \
4655 V(315) \
4656 V(316) \
4657 V(317) \
4658 V(318) \
4659 V(319) \
4660 V(320) \
4661 V(321) \
4662 V(322) \
4663 V(323) \
4664 V(324) \
4665 V(325) \
4666 V(326) \
4667 V(327) \
4668 V(328) \
4669 V(329) \
4670 V(330) \
4671 V(331) \
4672 V(332) \
4673 V(333) \
4674 V(334) \
4675 V(335) \
4676 V(336) \
4677 V(337) \
4678 V(338) \
4679 V(339) \
4680 V(340) \
4681 V(341) \
4682 V(342) \
4683 V(343) \
4684 V(344) \
4685 V(345) \
4686 V(346) \
4687 V(347) \
4688 V(348) \
4689 V(349) \
4690 V(350) \
4691 V(351) \
4692 V(352) \
4693 V(353) \
4694 V(354) \
4695 V(355) \
4696 V(356) \
4697 V(357) \
4698 V(358) \
4699 V(359) \
4700 V(360) \
4701 V(361) \
4702 V(362) \
4703 V(363) \
4704 V(364) \
4705 V(365) \
4706 V(366) \
4707 V(367) \
4708 V(368) \
4709 V(369) \
4710 V(370) \
4711 V(371) \
4712 V(372) \
4713 V(373) \
4714 V(374) \
4715 V(375) \
4716 V(376) \
4717 V(377) \
4718 V(378) \
4719 V(379) \
4720 V(380) \
4721 V(381) \
4722 V(382) \
4723 V(383) \
4724 V(384) \
4725 V(385) \
4726 V(386) \
4727 V(387) \
4728 V(388) \
4729 V(389) \
4730 V(390) \
4731 V(391) \
4732 V(392) \
4733 V(393) \
4734 V(394) \
4735 V(395) \
4736 V(396) \
4737 V(397) \
4738 V(398) \
4739 V(399) \
4740 V(400) \
4741 V(401) \
4742 V(402) \
4743 V(403) \
4744 V(404) \
4745 V(405) \
4746 V(406) \
4747 V(407) \
4748 V(408) \
4749 V(409) \
4750 V(410) \
4751 V(411) \
4752 V(412) \
4753 V(413) \
4754 V(414) \
4755 V(415) \
4756 V(416) \
4757 V(417) \
4758 V(418) \
4759 V(419) \
4760 V(420) \
4761 V(421) \
4762 V(422) \
4763 V(423) \
4764 V(424) \
4765 V(425) \
4766 V(426) \
4767 V(427) \
4768 V(428) \
4769 V(429) \
4770 V(430) \
4771 V(431) \
4772 V(432) \
4773 V(433) \
4774 V(434) \
4775 V(435) \
4776 V(436) \
4777 V(437) \
4778 V(438) \
4779 V(439) \
4780 V(440) \
4781 V(441) \
4782 V(442) \
4783 V(443) \
4784 V(444) \
4785 V(445) \
4786 V(446) \
4787 V(447) \
4788 V(448) \
4789 V(449) \
4790 V(450) \
4791 V(451) \
4792 V(452) \
4793 V(453) \
4794 V(454) \
4795 V(455) \
4796 V(456) \
4797 V(457) \
4798 V(458) \
4799 V(459) \
4800 V(460) \
4801 V(461) \
4802 V(462) \
4803 V(463) \
4804 V(464) \
4805 V(465) \
4806 V(466) \
4807 V(467) \
4808 V(468) \
4809 V(469) \
4810 V(470) \
4811 V(471) \
4812 V(472) \
4813 V(473) \
4814 V(474) \
4815 V(475) \
4816 V(476) \
4817 V(477) \
4818 V(478) \
4819 V(479) \
4820 V(480) \
4821 V(481) \
4822 V(482) \
4823 V(483) \
4824 V(484) \
4825 V(485) \
4826 V(486) \
4827 V(487) \
4828 V(488) \
4829 V(489) \
4830 V(490) \
4831 V(491) \
4832 V(492) \
4833 V(493) \
4834 V(494) \
4835 V(495) \
4836 V(496) \
4837 V(497) \
4838 V(498) \
4839 V(499) \
4840 V(500) \
4841 V(501) \
4842 V(502) \
4843 V(503) \
4844 V(504) \
4845 V(505) \
4846 V(506) \
4847 V(507) \
4848 V(508) \
4849 V(509) \
4850 V(510) \
4851 V(511)
4852
4854
4855#undef FINALIZER_CROSS_GEN_TEST_CASE
4856
4857// Force the marker to add a FinalizerEntry to the store buffer during marking.
4858//
4859// This test requires two entries, one in new space, one in old space.
4860// The scavenger should run first, adding the entry to collected_entries.
4861// The marker runs right after, swapping the collected_entries with the entry
4862// in old space, _and_ setting the next field to the entry in new space.
4863// This forces the entry to be added to the store-buffer _during_ marking.
4864//
4865// Then, the compacter needs to be used. Which will move the entry in old
4866// space.
4867//
4868// If the thread's store buffer block is not released after that, the compactor
4869// will not update it, causing an outdated address to be released to the store
4870// buffer later.
4871//
4872// This causes two types of errors to trigger with --verify-store-buffer:
4873// 1. We see the address in the store buffer but the object is no entry there.
4874// Also can cause segfaults on reading garbage or unallocated memory.
4875// 2. We see the entry has a marked bit, but can't find it in the store buffer.
4876ISOLATE_UNIT_TEST_CASE(Finalizer_Regress_48843) {
4877#ifdef DEBUG
4878 SetFlagScope<bool> sfs(&FLAG_trace_finalizers, true);
4879 SetFlagScope<bool> sfs2(&FLAG_verify_store_buffer, true);
4880#endif
4881 SetFlagScope<bool> sfs3(&FLAG_use_compactor, true);
4882
4883 const auto& finalizer = Finalizer::Handle(Finalizer::New(Heap::kOld));
4884 finalizer.set_isolate(thread->isolate());
4885
4886 const auto& detach1 =
4888 const auto& token1 = String::Handle(OneByteString::New("token1", Heap::kNew));
4889 const auto& detach2 =
4891 const auto& token2 = String::Handle(OneByteString::New("token2", Heap::kOld));
4892
4893 {
4894 HANDLESCOPE(thread);
4895 const auto& entry1 =
4897 entry1.set_detach(detach1);
4898 entry1.set_token(token1);
4899
4900 const auto& entry2 =
4902 entry2.set_detach(detach2);
4903 entry2.set_token(token2);
4904
4905 {
4906 HANDLESCOPE(thread);
4907 const auto& value1 =
4909 entry1.set_value(value1);
4910 const auto& value2 =
4912 entry2.set_value(value2);
4913 // Lose both values.
4914 }
4915
4916 // First collect new space.
4917 GCTestHelper::CollectNewSpace();
4918 // Then old space, this will make the old space entry point to the new
4919 // space entry.
4920 // Also, this must be a mark compact, not a mark sweep, to move the entry.
4921 GCTestHelper::CollectOldSpace();
4922 }
4923
4924 // Imagine callbacks running.
4925 // Entries themselves become unreachable.
4926 finalizer.set_entries_collected(
4928
4929 // There should be a single entry in the store buffer.
4930 // And it should crash when seeing the address in the buffer.
4931 GCTestHelper::CollectNewSpace();
4932
4933 // We should no longer be processing the entries.
4934 GCTestHelper::CollectOldSpace();
4935 GCTestHelper::CollectNewSpace();
4936}
4937
4939 intptr_t* token = reinterpret_cast<intptr_t*>(peer);
4940 (*token)++;
4941}
4942
4944 Thread* thread,
4945 Heap::Space* spaces,
4946 bool collect_new_space,
4947 bool evacuate_new_space_and_collect_old_space,
4948 bool clear_value_1,
4949 bool clear_value_2,
4950 bool clear_detach_1,
4951 bool clear_detach_2) {
4952#ifdef DEBUG
4953 SetFlagScope<bool> sfs(&FLAG_trace_finalizers, true);
4954#endif
4955
4956 intptr_t token1_memory = 0;
4957 intptr_t token2_memory = 0;
4958
4959 MessageHandler* handler = thread->isolate()->message_handler();
4960 // We're reusing the isolate in a loop, so there are messages from previous
4961 // runs of this test.
4962 intptr_t queue_length_start = 0;
4963 {
4965 queue_length_start = aq.queue()->Length();
4966 }
4967
4970 spaces[3]));
4971
4972 const auto& finalizer =
4974 finalizer.set_callback(callback);
4975 finalizer.set_isolate(thread->isolate());
4976
4977 const auto& isolate_finalizers =
4980 weak1.set_target(finalizer);
4981 isolate_finalizers.Add(weak1);
4982 thread->isolate()->set_finalizers(isolate_finalizers);
4983
4984 const auto& all_entries = Set::Handle(Set::NewDefault());
4985 finalizer.set_all_entries(all_entries);
4986 const auto& all_entries_data = Array::Handle(all_entries.data());
4987 THR_Print("entry1 space: %s\n", spaces[1] == Heap::kNew ? "new" : "old");
4988 const auto& entry1 =
4989 FinalizerEntry::Handle(FinalizerEntry::New(finalizer, spaces[1]));
4990 all_entries_data.SetAt(0, entry1);
4991 THR_Print("entry2 space: %s\n", spaces[2] == Heap::kNew ? "new" : "old");
4992 const auto& entry2 =
4993 FinalizerEntry::Handle(FinalizerEntry::New(finalizer, spaces[2]));
4994 all_entries_data.SetAt(1, entry2);
4995 all_entries.set_used_data(2); // Don't bother setting the index.
4996
4997 const intptr_t external_size1 = 1024;
4998 const intptr_t external_size2 = 2048;
4999 entry1.set_external_size(external_size1);
5000 entry2.set_external_size(external_size2);
5001 IsolateGroup::Current()->heap()->AllocatedExternal(external_size1, spaces[5]);
5002 IsolateGroup::Current()->heap()->AllocatedExternal(external_size2, spaces[7]);
5003
5004 auto& value1 = String::Handle();
5005 auto& detach1 = String::Handle();
5006 const auto& token1 = Pointer::Handle(
5007 Pointer::New(reinterpret_cast<uword>(&token1_memory), spaces[3]));
5008 entry1.set_token(token1);
5009
5010 auto& value2 = String::Handle();
5011 auto& detach2 = String::Handle();
5012 const auto& token2 = Pointer::Handle(
5013 Pointer::New(reinterpret_cast<uword>(&token2_memory), spaces[4]));
5014 entry2.set_token(token2);
5015 entry2.set_detach(detach2);
5016
5017 {
5018 HANDLESCOPE(thread);
5019 auto& object = String::Handle();
5020
5021 THR_Print("value1 space: %s\n", spaces[5] == Heap::kNew ? "new" : "old");
5022 object ^= OneByteString::New("value1", spaces[5]);
5023 entry1.set_value(object);
5024 if (!clear_value_1) {
5025 value1 = object.ptr();
5026 }
5027
5028 object ^= OneByteString::New("detach", spaces[6]);
5029 entry1.set_detach(object);
5030 if (!clear_detach_1) {
5031 detach1 = object.ptr();
5032 }
5033
5034 THR_Print("value2 space: %s\n", spaces[7] == Heap::kNew ? "new" : "old");
5035 object ^= OneByteString::New("value2", spaces[7]);
5036 entry2.set_value(object);
5037 if (!clear_value_2) {
5038 value2 = object.ptr();
5039 }
5040
5041 object ^= OneByteString::New("detach", spaces[8]);
5042 entry2.set_detach(object);
5043 if (!clear_detach_2) {
5044 detach2 = object.ptr();
5045 }
5046 }
5047
5048 THR_Print("CollectOldSpace\n");
5049 GCTestHelper::CollectOldSpace();
5050 if (collect_new_space) {
5051 THR_Print("CollectNewSpace\n");
5052 GCTestHelper::CollectNewSpace();
5053 }
5054 if (evacuate_new_space_and_collect_old_space) {
5055 THR_Print("CollectAllGarbage\n");
5057 }
5058
5059 EXPECT((entry1.value() == Object::null()) ^ !clear_value_1);
5060 EXPECT((entry2.value() == Object::null()) ^ !clear_value_2);
5061 EXPECT((entry1.detach() == Object::null()) ^ !clear_detach_1);
5062 EXPECT((entry2.detach() == Object::null()) ^ !clear_detach_2);
5063 EXPECT_NE(Object::null(), entry1.token());
5064 EXPECT_NE(Object::null(), entry2.token());
5065
5066 const intptr_t expect_num_cleared =
5067 (clear_value_1 ? 1 : 0) + (clear_value_2 ? 1 : 0);
5068 EXPECT_EQ(expect_num_cleared,
5069 NumEntries(FinalizerEntry::Handle(finalizer.entries_collected())));
5070
5071 EXPECT_EQ(clear_value_1 ? 1 : 0, token1_memory);
5072 EXPECT_EQ(clear_value_2 ? 1 : 0, token2_memory);
5073
5074 const intptr_t expect_num_messages = expect_num_cleared == 0 ? 0 : 1;
5075 {
5076 // Acquire ownership of message handler queues.
5078 EXPECT_EQ(expect_num_messages + queue_length_start, aq.queue()->Length());
5079 }
5080
5081 // Simulate detachments.
5082 entry1.set_token(entry1);
5083 entry2.set_token(entry2);
5084 all_entries_data.SetAt(0, Object::Handle(Object::null()));
5085 all_entries_data.SetAt(1, Object::Handle(Object::null()));
5086 all_entries.set_used_data(0);
5087}
5088
5090 intptr_t test_i) {
5091 ASSERT(test_i < (1 << kFinalizerTwoEntriesNumObjects));
5093 for (intptr_t i = 0; i < kFinalizerTwoEntriesNumObjects; i++) {
5094 spaces[i] = ((test_i >> i) & 0x1) == 0x1 ? Heap::kOld : Heap::kNew;
5095 }
5096 // Either collect or evacuate new space.
5097 for (const bool collect_new_space : {true, false}) {
5098 // Always run old space collection after new space.
5099 const bool evacuate_new_space_and_collect_old_space = true;
5100 const bool clear_value_1 = true;
5101 const bool clear_value_2 = true;
5102 const bool clear_detach_1 = false;
5103 const bool clear_detach_2 = false;
5104 THR_Print(
5105 "collect_new_space: %s evacuate_new_space_and_collect_old_space: %s\n",
5106 collect_new_space ? "true" : "false",
5107 evacuate_new_space_and_collect_old_space ? "true" : "false");
5108 NativeFinalizer_TwoEntriesCrossGen(thread, spaces, collect_new_space,
5109 evacuate_new_space_and_collect_old_space,
5110 clear_value_1, clear_value_2,
5111 clear_detach_1, clear_detach_2);
5112 }
5113}
5114
5115#define FINALIZER_NATIVE_CROSS_GEN_TEST_CASE(n) \
5116 ISOLATE_UNIT_TEST_CASE(NativeFinalizer_CrossGen_##n) { \
5117 NativeFinalizer_TwoEntriesCrossGen(thread, n); \
5118 }
5119
5121
5122#undef FINALIZER_NATIVE_CROSS_GEN_TEST_CASE
5123
5124#undef REPEAT_512
5125
5126TEST_CASE(IsIsolateUnsendable) {
5127 Zone* const zone = Thread::Current()->zone();
5128
5129 const char* kScript = R"(
5130import 'dart:ffi';
5131
5132class AImpl implements A {}
5133class ASub extends A {}
5134// Wonky class order and non-alphabetic naming on purpose.
5135class C extends Z {}
5136class E extends D {}
5137class A implements Finalizable {}
5138class Z implements A {}
5139class D implements C {}
5140class X extends E {}
5141)";
5142 Dart_Handle h_lib = TestCase::LoadTestScript(kScript, nullptr);
5143 EXPECT_VALID(h_lib);
5144
5145 TransitionNativeToVM transition(thread);
5146 const Library& lib = Library::CheckedHandle(zone, Api::UnwrapHandle(h_lib));
5147 EXPECT(!lib.IsNull());
5148
5149 const auto& class_x = Class::Handle(zone, GetClass(lib, "X"));
5150 class_x.EnsureIsFinalized(thread);
5151 EXPECT(class_x.is_isolate_unsendable());
5152
5153 const auto& class_a_impl = Class::Handle(zone, GetClass(lib, "AImpl"));
5154 class_a_impl.EnsureIsFinalized(thread);
5155 EXPECT(class_a_impl.is_isolate_unsendable());
5156
5157 const auto& class_a_sub = Class::Handle(zone, GetClass(lib, "ASub"));
5158 class_a_sub.EnsureIsFinalized(thread);
5159 EXPECT(class_a_sub.is_isolate_unsendable());
5160}
5161
5162TEST_CASE(ImplementorCid) {
5163 const char* kScriptChars = R"(
5164abstract class AInterface {}
5165
5166abstract class BInterface {}
5167class BImplementation implements BInterface {}
5168
5169abstract class CInterface {}
5170class CImplementation1 implements CInterface {}
5171class CImplementation2 implements CInterface {}
5172
5173abstract class DInterface {}
5174abstract class DSubinterface implements DInterface {}
5175
5176abstract class EInterface {}
5177abstract class ESubinterface implements EInterface {}
5178class EImplementation implements ESubinterface {}
5179
5180abstract class FInterface {}
5181abstract class FSubinterface implements FInterface {}
5182class FImplementation1 implements FSubinterface {}
5183class FImplementation2 implements FSubinterface {}
5184
5185main() {
5186 new BImplementation();
5187 new CImplementation1();
5188 new CImplementation2();
5189 new EImplementation();
5190 new FImplementation1();
5191 new FImplementation2();
5192}
5193)";
5194 Dart_Handle h_lib = TestCase::LoadTestScript(kScriptChars, nullptr);
5195 EXPECT_VALID(h_lib);
5196 Dart_Handle result = Dart_Invoke(h_lib, NewString("main"), 0, nullptr);
5198
5199 TransitionNativeToVM transition(thread);
5200 const Library& lib =
5201 Library::CheckedHandle(thread->zone(), Api::UnwrapHandle(h_lib));
5202 EXPECT(!lib.IsNull());
5203
5204 const Class& AInterface = Class::Handle(GetClass(lib, "AInterface"));
5205 EXPECT_EQ(AInterface.implementor_cid(), kIllegalCid);
5206
5207 const Class& BInterface = Class::Handle(GetClass(lib, "BInterface"));
5208 const Class& BImplementation =
5209 Class::Handle(GetClass(lib, "BImplementation"));
5210 EXPECT_EQ(BInterface.implementor_cid(), BImplementation.id());
5211 EXPECT_EQ(BImplementation.implementor_cid(), BImplementation.id());
5212
5213 const Class& CInterface = Class::Handle(GetClass(lib, "CInterface"));
5214 const Class& CImplementation1 =
5215 Class::Handle(GetClass(lib, "CImplementation1"));
5216 const Class& CImplementation2 =
5217 Class::Handle(GetClass(lib, "CImplementation2"));
5218 EXPECT_EQ(CInterface.implementor_cid(), kDynamicCid);
5219 EXPECT_EQ(CImplementation1.implementor_cid(), CImplementation1.id());
5220 EXPECT_EQ(CImplementation2.implementor_cid(), CImplementation2.id());
5221
5222 const Class& DInterface = Class::Handle(GetClass(lib, "DInterface"));
5223 const Class& DSubinterface = Class::Handle(GetClass(lib, "DSubinterface"));
5224 EXPECT_EQ(DInterface.implementor_cid(), kIllegalCid);
5225 EXPECT_EQ(DSubinterface.implementor_cid(), kIllegalCid);
5226
5227 const Class& EInterface = Class::Handle(GetClass(lib, "EInterface"));
5228 const Class& ESubinterface = Class::Handle(GetClass(lib, "ESubinterface"));
5229 const Class& EImplementation =
5230 Class::Handle(GetClass(lib, "EImplementation"));
5231 EXPECT_EQ(EInterface.implementor_cid(), EImplementation.id());
5232 EXPECT_EQ(ESubinterface.implementor_cid(), EImplementation.id());
5233 EXPECT_EQ(EImplementation.implementor_cid(), EImplementation.id());
5234
5235 const Class& FInterface = Class::Handle(GetClass(lib, "FInterface"));
5236 const Class& FSubinterface = Class::Handle(GetClass(lib, "FSubinterface"));
5237 const Class& FImplementation1 =
5238 Class::Handle(GetClass(lib, "FImplementation1"));
5239 const Class& FImplementation2 =
5240 Class::Handle(GetClass(lib, "FImplementation2"));
5241 EXPECT_EQ(FInterface.implementor_cid(), kDynamicCid);
5242 EXPECT_EQ(FSubinterface.implementor_cid(), kDynamicCid);
5243 EXPECT_EQ(FImplementation1.implementor_cid(), FImplementation1.id());
5244 EXPECT_EQ(FImplementation2.implementor_cid(), FImplementation2.id());
5245}
5246
5248 const MirrorReference& reference =
5250 Object& initial_referent = Object::Handle(reference.referent());
5251 EXPECT(initial_referent.IsNull());
5252
5254 EXPECT(!library.IsNull());
5255 EXPECT(library.IsLibrary());
5256 reference.set_referent(library);
5257 const Object& returned_referent = Object::Handle(reference.referent());
5258 EXPECT(returned_referent.IsLibrary());
5259 EXPECT_EQ(returned_referent.ptr(), library.ptr());
5260
5261 const MirrorReference& other_reference =
5263 EXPECT_NE(reference.ptr(), other_reference.ptr());
5264 other_reference.set_referent(library);
5265 EXPECT_NE(reference.ptr(), other_reference.ptr());
5266 EXPECT_EQ(reference.referent(), other_reference.referent());
5267
5268 Object& obj = Object::Handle(reference.ptr());
5269 EXPECT(obj.IsMirrorReference());
5270}
5271
5272static FunctionPtr GetFunction(const Class& cls, const char* name) {
5273 Thread* thread = Thread::Current();
5274 const auto& error = cls.EnsureIsFinalized(thread);
5275 EXPECT(error == Error::null());
5277 Z, cls, String::Handle(String::New(name))));
5278 EXPECT(!result.IsNull());
5279 return result.ptr();
5280}
5281
5282static FunctionPtr GetStaticFunction(const Class& cls, const char* name) {
5283 const auto& error = cls.EnsureIsFinalized(Thread::Current());
5284 EXPECT(error == Error::null());
5287 EXPECT(!result.IsNull());
5288 return result.ptr();
5289}
5290
5291static FieldPtr GetField(const Class& cls, const char* name) {
5292 const Field& field =
5294 EXPECT(!field.IsNull());
5295 return field.ptr();
5296}
5297
5298ISOLATE_UNIT_TEST_CASE(FindClosureIndex) {
5299 // Allocate the class first.
5300 const String& class_name = String::Handle(Symbols::New(thread, "MyClass"));
5301 const Script& script = Script::Handle();
5303 const Array& functions = Array::Handle(Array::New(1));
5304
5305 Function& parent = Function::Handle();
5306 const String& parent_name = String::Handle(Symbols::New(thread, "foo_papa"));
5308 parent = Function::New(signature, parent_name,
5309 UntaggedFunction::kRegularFunction, false, false,
5310 false, false, false, cls, TokenPosition::kMinSource);
5311 functions.SetAt(0, parent);
5312 {
5313 SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
5314 cls.SetFunctions(functions);
5315 }
5316
5318 const String& function_name = String::Handle(Symbols::New(thread, "foo"));
5321 function.set_kernel_offset(42);
5322 // Add closure function to class.
5323 {
5324 SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
5326 }
5327
5328 // The closure should return a valid index.
5329 intptr_t good_closure_index =
5331 EXPECT_GE(good_closure_index, 0);
5332 // The parent function should return an invalid index.
5333 intptr_t bad_closure_index = ClosureFunctionsCache::FindClosureIndex(parent);
5334 EXPECT_EQ(bad_closure_index, -1);
5335
5336 // Retrieve closure function via index.
5337 Function& func_from_index = Function::Handle();
5338 func_from_index ^=
5340 // Same closure function.
5341 EXPECT_EQ(func_from_index.ptr(), function.ptr());
5342}
5343
5344ISOLATE_UNIT_TEST_CASE(FindInvocationDispatcherFunctionIndex) {
5345 const String& class_name = String::Handle(Symbols::New(thread, "MyClass"));
5346 const Script& script = Script::Handle();
5349
5350 const Array& functions = Array::Handle(Array::New(1));
5351 Function& parent = Function::Handle();
5352 const String& parent_name = String::Handle(Symbols::New(thread, "foo_papa"));
5354 parent = Function::New(signature, parent_name,
5355 UntaggedFunction::kRegularFunction, false, false,
5356 false, false, false, cls, TokenPosition::kMinSource);
5357 functions.SetAt(0, parent);
5358 {
5359 SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
5360 cls.SetFunctions(functions);
5361 cls.Finalize();
5362 }
5363
5364 // Add invocation dispatcher.
5365 const String& invocation_dispatcher_name =
5366 String::Handle(Symbols::New(thread, "myMethod"));
5367 const Array& args_desc = Array::Handle(ArgumentsDescriptor::NewBoxed(0, 1));
5368 Function& invocation_dispatcher = Function::Handle();
5369 invocation_dispatcher ^= cls.GetInvocationDispatcher(
5370 invocation_dispatcher_name, args_desc,
5371 UntaggedFunction::kNoSuchMethodDispatcher, true /* create_if_absent */);
5372 EXPECT(!invocation_dispatcher.IsNull());
5373 // Get index to function.
5374 intptr_t invocation_dispatcher_index =
5375 cls.FindInvocationDispatcherFunctionIndex(invocation_dispatcher);
5376 // Expect a valid index.
5377 EXPECT_GE(invocation_dispatcher_index, 0);
5378 // Retrieve function through index.
5379 Function& invocation_dispatcher_from_index = Function::Handle();
5380 invocation_dispatcher_from_index ^=
5381 cls.InvocationDispatcherFunctionFromIndex(invocation_dispatcher_index);
5382 // Same function.
5383 EXPECT_EQ(invocation_dispatcher.ptr(),
5384 invocation_dispatcher_from_index.ptr());
5385 // Test function not found case.
5386 const Function& bad_function = Function::Handle(Function::null());
5387 intptr_t bad_invocation_dispatcher_index =
5388 cls.FindInvocationDispatcherFunctionIndex(bad_function);
5389 EXPECT_EQ(bad_invocation_dispatcher_index, -1);
5390}
5391
5392static void PrintMetadata(const char* name, const Object& data) {
5393 if (data.IsError()) {
5394 OS::PrintErr("Error in metadata evaluation for %s: '%s'\n", name,
5395 Error::Cast(data).ToErrorCString());
5396 }
5397 EXPECT(data.IsArray());
5398 const Array& metadata = Array::Cast(data);
5399 OS::PrintErr("Metadata for %s has %" Pd " values:\n", name,
5400 metadata.Length());
5401 Object& elem = Object::Handle();
5402 for (int i = 0; i < metadata.Length(); i++) {
5403 elem = metadata.At(i);
5404 OS::PrintErr(" %d: %s\n", i, elem.ToCString());
5405 }
5406}
5407
5408TEST_CASE(Metadata) {
5409 // clang-format off
5410 const char* kScriptChars =
5411 "@metafoo \n"
5412 "class Meta { \n"
5413 " final m; \n"
5414 " const Meta(this.m); \n"
5415 "} \n"
5416 " \n"
5417 "const metafoo = 'metafoo'; \n"
5418 "const metabar = 'meta' 'bar'; \n"
5419 " \n"
5420 "@metafoo \n"
5421 "@Meta(0) String? gVar; \n"
5422 " \n"
5423 "@metafoo \n"
5424 "get tlGetter => gVar; \n"
5425 " \n"
5426 "@metabar \n"
5427 "class A { \n"
5428 " @metafoo \n"
5429 " @metabar \n"
5430 " @Meta('baz') \n"
5431 " var aField; \n"
5432 " \n"
5433 " @metabar @Meta('baa') \n"
5434 " int aFunc(a,b) => a + b; \n"
5435 "} \n"
5436 " \n"
5437 "@Meta('main') \n"
5438 "A main() { \n"
5439 " return A(); \n"
5440 "} \n";
5441 // clang-format on
5442
5443 Dart_Handle h_lib = TestCase::LoadTestScript(kScriptChars, nullptr);
5444 EXPECT_VALID(h_lib);
5445 Dart_Handle result = Dart_Invoke(h_lib, NewString("main"), 0, nullptr);
5447 TransitionNativeToVM transition(thread);
5448 Library& lib = Library::Handle();
5449 lib ^= Api::UnwrapHandle(h_lib);
5450 EXPECT(!lib.IsNull());
5451 const Class& class_a = Class::Handle(GetClass(lib, "A"));
5452 Object& res = Object::Handle(lib.GetMetadata(class_a));
5453 PrintMetadata("A", res);
5454
5455 const Class& class_meta = Class::Handle(GetClass(lib, "Meta"));
5456 res = lib.GetMetadata(class_meta);
5457 PrintMetadata("Meta", res);
5458
5459 Field& field = Field::Handle(GetField(class_a, "aField"));
5460 res = lib.GetMetadata(field);
5461 PrintMetadata("A.aField", res);
5462
5463 Function& func = Function::Handle(GetFunction(class_a, "aFunc"));
5464 res = lib.GetMetadata(func);
5465 PrintMetadata("A.aFunc", res);
5466
5467 func = lib.LookupFunctionAllowPrivate(
5468 String::Handle(Symbols::New(thread, "main")));
5469 EXPECT(!func.IsNull());
5470 res = lib.GetMetadata(func);
5471 PrintMetadata("main", res);
5472
5473 func = lib.LookupFunctionAllowPrivate(
5474 String::Handle(Symbols::New(thread, "get:tlGetter")));
5475 EXPECT(!func.IsNull());
5476 res = lib.GetMetadata(func);
5477 PrintMetadata("tlGetter", res);
5478
5479 field =
5481 EXPECT(!field.IsNull());
5482 res = lib.GetMetadata(field);
5483 PrintMetadata("gVar", res);
5484}
5485
5486TEST_CASE(FunctionSourceFingerprint) {
5487 const char* kScriptChars =
5488 "class A {\n"
5489 " static test1(int a) {\n"
5490 " return a > 1 ? a + 1 : a;\n"
5491 " }\n"
5492 " static test2(a) {\n"
5493 " return a > 1 ? a + 1 : a;\n"
5494 " }\n"
5495 " static test3(b) {\n"
5496 " return b > 1 ? b + 1 : b;\n"
5497 " }\n"
5498 " static test4(b) {\n"
5499 " return b > 1 ? b - 1 : b;\n"
5500 " }\n"
5501 " static test5(b) {\n"
5502 " return b > 1 ? b - 2 : b;\n"
5503 " }\n"
5504 " test6(int a) {\n"
5505 " return a > 1 ? a + 1 : a;\n"
5506 " }\n"
5507 "}\n"
5508 "class B {\n"
5509 " static /* Different declaration style. */\n"
5510 " test1(int a) {\n"
5511 " /* Returns a + 1 for a > 1, a otherwise. */\n"
5512 " return a > 1 ?\n"
5513 " a + 1 :\n"
5514 " a;\n"
5515 " }\n"
5516 " static test5(b) {\n"
5517 " return b > 1 ?\n"
5518 " b - 2 : b;\n"
5519 " }\n"
5520 " test6(int a) {\n"
5521 " return a > 1 ? a + 1 : a;\n"
5522 " }\n"
5523 "}";
5524 TestCase::LoadTestScript(kScriptChars, nullptr);
5525 TransitionNativeToVM transition(thread);
5528 const Library& lib = Library::Handle(Library::LookupLibrary(thread, name));
5529 EXPECT(!lib.IsNull());
5530
5531 const Class& class_a =
5533 const Class& class_b =
5535 const Function& a_test1 =
5536 Function::Handle(GetStaticFunction(class_a, "test1"));
5537 const Function& b_test1 =
5538 Function::Handle(GetStaticFunction(class_b, "test1"));
5539 const Function& a_test2 =
5540 Function::Handle(GetStaticFunction(class_a, "test2"));
5541 const Function& a_test3 =
5542 Function::Handle(GetStaticFunction(class_a, "test3"));
5543 const Function& a_test4 =
5544 Function::Handle(GetStaticFunction(class_a, "test4"));
5545 const Function& a_test5 =
5546 Function::Handle(GetStaticFunction(class_a, "test5"));
5547 const Function& b_test5 =
5548 Function::Handle(GetStaticFunction(class_b, "test5"));
5549 const Function& a_test6 = Function::Handle(GetFunction(class_a, "test6"));
5550 const Function& b_test6 = Function::Handle(GetFunction(class_b, "test6"));
5551
5552 EXPECT_EQ(a_test1.SourceFingerprint(), b_test1.SourceFingerprint());
5553 EXPECT_NE(a_test1.SourceFingerprint(), a_test2.SourceFingerprint());
5554 EXPECT_NE(a_test2.SourceFingerprint(), a_test3.SourceFingerprint());
5555 EXPECT_NE(a_test3.SourceFingerprint(), a_test4.SourceFingerprint());
5556 EXPECT_NE(a_test4.SourceFingerprint(), a_test5.SourceFingerprint());
5557 EXPECT_EQ(a_test5.SourceFingerprint(), b_test5.SourceFingerprint());
5558 // Although a_test6's receiver type is different than b_test6's receiver type,
5559 // the fingerprints are identical. The token stream does not reflect the
5560 // receiver's type. This is not a problem, since we recognize functions
5561 // of a given class and of a given name.
5562 EXPECT_EQ(a_test6.SourceFingerprint(), b_test6.SourceFingerprint());
5563}
5564
5565#ifndef PRODUCT
5566
5567TEST_CASE(FunctionWithBreakpointNotInlined) {
5568 const char* kScriptChars =
5569 "class A {\n"
5570 " a() {\n"
5571 " }\n"
5572 " b() {\n"
5573 " a();\n" // This is line 5.
5574 " }\n"
5575 "}\n"
5576 "test() {\n"
5577 " new A().b();\n"
5578 "}";
5579 const int kBreakpointLine = 5;
5580 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
5581 EXPECT_VALID(lib);
5582
5583 // Run function A.b one time.
5584 Dart_Handle result = Dart_Invoke(lib, NewString("test"), 0, nullptr);
5586
5587 // With no breakpoint, function A.b is inlineable.
5588 {
5589 TransitionNativeToVM transition(thread);
5591 const Library& vmlib =
5593 EXPECT(!vmlib.IsNull());
5594 const Class& class_a = Class::Handle(
5595 vmlib.LookupClass(String::Handle(Symbols::New(thread, "A"))));
5596 Function& func_b = Function::Handle(GetFunction(class_a, "b"));
5597 EXPECT(func_b.CanBeInlined());
5598 }
5599
5600 result = Dart_SetBreakpoint(NewString(TestCase::url()), kBreakpointLine);
5602
5603 // After setting a breakpoint in a function A.b, it is no longer inlineable.
5604 {
5605 TransitionNativeToVM transition(thread);
5607 const Library& vmlib =
5609 EXPECT(!vmlib.IsNull());
5610 const Class& class_a = Class::Handle(
5611 vmlib.LookupClass(String::Handle(Symbols::New(thread, "A"))));
5612 Function& func_b = Function::Handle(GetFunction(class_a, "b"));
5613 EXPECT(!func_b.CanBeInlined());
5614 }
5615}
5616
5618 // Refers to the DeoptimizeFramesWhenSettingBreakpoint function below.
5619 const int kBreakpointLine = 8;
5620
5621 // This will force deoptimization of functions on stack.
5622 // Function on stack has to be optimized, since we want to trigger debuggers
5623 // on-stack deoptimization flow when we set a breakpoint.
5625 Dart_SetBreakpoint(NewString(TestCase::url()), kBreakpointLine);
5627}
5628
5630 int argument_count,
5631 bool* auto_setup_scope) {
5632 ASSERT(auto_setup_scope != nullptr);
5633 *auto_setup_scope = true;
5634 const char* cstr = nullptr;
5637 EXPECT_STREQ(cstr, "setBreakpoint");
5638 return &SetBreakpoint;
5639}
5640
5641TEST_CASE(DeoptimizeFramesWhenSettingBreakpoint) {
5642 const char* kOriginalScript = "test() {}";
5643
5644 Dart_Handle lib = TestCase::LoadTestScript(kOriginalScript, nullptr);
5645 EXPECT_VALID(lib);
5647
5648 // Get unoptimized code for functions so they can be optimized.
5649 Dart_Handle result = Dart_Invoke(lib, NewString("test"), 0, nullptr);
5651
5652 // Launch second isolate so that running with stopped mutators during
5653 // deoptimizattion requests a safepoint.
5656 char* error = nullptr;
5657 Dart_Isolate child = Dart_CreateIsolateInGroup(parent, "child",
5658 /*shutdown_callback=*/nullptr,
5659 /*cleanup_callback=*/nullptr,
5660 /*peer=*/nullptr, &error);
5661 EXPECT_NE(nullptr, child);
5662 EXPECT_EQ(nullptr, error);
5664 Dart_EnterIsolate(parent);
5665
5666 const char* kReloadScript =
5667 R"(
5668 @pragma("vm:external-name", "setBreakpoint")
5669 external setBreakpoint();
5670 baz() {}
5671 test() {
5672 if (true) {
5673 setBreakpoint();
5674 } else {
5675 baz(); // this line gets a breakpoint
5676 }
5677 }
5678 )";
5679 lib = TestCase::ReloadTestScript(kReloadScript);
5680 EXPECT_VALID(lib);
5681
5682 {
5683 TransitionNativeToVM transition(thread);
5685 const Library& vmlib =
5687 EXPECT(!vmlib.IsNull());
5688 Function& func_test = Function::Handle(GetFunction(vmlib, "test"));
5689 Compiler::EnsureUnoptimizedCode(thread, func_test);
5690 Compiler::CompileOptimizedFunction(thread, func_test);
5692 }
5693
5694 result = Dart_Invoke(lib, NewString("test"), 0, nullptr);
5696
5697 // Make sure child isolate finishes.
5700 {
5701 bool result =
5702 Dart_RunLoopAsync(/*errors_are_fatal=*/true,
5703 /*on_error_port=*/0, /*on_exit_port=*/0, &error);
5704 EXPECT_EQ(true, result);
5706 EXPECT_EQ(nullptr, error);
5707 Dart_EnterIsolate(parent);
5708}
5709
5710class ToggleBreakpointTask : public ThreadPool::Task {
5711 public:
5712 ToggleBreakpointTask(IsolateGroup* isolate_group,
5713 Dart_Isolate isolate,
5714 std::atomic<bool>* done)
5715 : isolate_group_(isolate_group), isolate_(isolate), done_(done) {}
5716 virtual void Run() {
5717 Dart_EnterIsolate(isolate_);
5719 const int kBreakpointLine = 5; // in the dart script below
5720 Thread* t = Thread::Current();
5721 for (intptr_t i = 0; i < 1000; i++) {
5723 Dart_SetBreakpoint(NewString(TestCase::url()), kBreakpointLine);
5725 int64_t breakpoint_id;
5726 {
5727 TransitionNativeToVM transition(t);
5728 Integer& breakpoint_id_handle = Integer::Handle();
5729 breakpoint_id_handle ^= Api::UnwrapHandle(result);
5730 breakpoint_id = breakpoint_id_handle.AsInt64Value();
5731 }
5734 }
5737 *done_ = true;
5738 }
5739
5740 private:
5741 IsolateGroup* isolate_group_;
5742 Dart_Isolate isolate_;
5743 std::atomic<bool>* done_;
5744};
5745
5746TEST_CASE(DartAPI_BreakpointLockRace) {
5747 const char* kScriptChars =
5748 "class A {\n"
5749 " a() {\n"
5750 " }\n"
5751 " b() {\n"
5752 " a();\n" // This is line 5.
5753 " }\n"
5754 "}\n"
5755 "test() {\n"
5756 " new A().b();\n"
5757 "}";
5758 // Create a test library and Load up a test script in it.
5759 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
5760 EXPECT_VALID(lib);
5761
5762 // Run function A.b one time.
5763 Dart_Handle result = Dart_Invoke(lib, NewString("test"), 0, nullptr);
5765
5766 // Launch second isolate so that running with stopped mutators during
5767 // deoptimizattion requests a safepoint.
5770 char* error = nullptr;
5771 Dart_Isolate child = Dart_CreateIsolateInGroup(parent, "child",
5772 /*shutdown_callback=*/nullptr,
5773 /*cleanup_callback=*/nullptr,
5774 /*peer=*/nullptr, &error);
5775 EXPECT_NE(nullptr, child);
5776 EXPECT_EQ(nullptr, error);
5778 Dart_EnterIsolate(parent);
5779
5780 // Run function A.b one time.
5781 std::atomic<bool> done = false;
5782 Dart::thread_pool()->Run<ToggleBreakpointTask>(IsolateGroup::Current(), child,
5783 &done);
5784
5785 while (!done) {
5786 ReloadParticipationScope allow_reload(thread);
5787 {
5788 TransitionNativeToVM transition(thread);
5789 const String& name = String::Handle(String::New(TestCase::url()));
5790 const Library& vmlib =
5792 EXPECT(!vmlib.IsNull());
5793 const Class& class_a = Class::Handle(
5794 vmlib.LookupClass(String::Handle(Symbols::New(thread, "A"))));
5795 Function& func_b = Function::Handle(GetFunction(class_a, "b"));
5796 func_b.CanBeInlined();
5797 }
5798 }
5799
5800 // Make sure child isolate finishes.
5803 {
5804 bool result =
5805 Dart_RunLoopAsync(/*errors_are_fatal=*/true,
5806 /*on_error_port=*/0, /*on_exit_port=*/0, &error);
5807 EXPECT_EQ(true, result);
5808 }
5809 EXPECT_EQ(nullptr, error);
5810 Dart_EnterIsolate(parent);
5811}
5812
5813ISOLATE_UNIT_TEST_CASE(SpecialClassesHaveEmptyArrays) {
5814 ObjectStore* object_store = IsolateGroup::Current()->object_store();
5815 Class& cls = Class::Handle();
5816 Object& array = Object::Handle();
5817
5818 cls = object_store->null_class();
5819 array = cls.fields();
5820 EXPECT(!array.IsNull());
5821 EXPECT(array.IsArray());
5822 array = cls.current_functions();
5823 EXPECT(!array.IsNull());
5824 EXPECT(array.IsArray());
5825
5826 cls = Object::void_class();
5827 array = cls.fields();
5828 EXPECT(!array.IsNull());
5829 EXPECT(array.IsArray());
5830 array = cls.current_functions();
5831 EXPECT(!array.IsNull());
5832 EXPECT(array.IsArray());
5833
5835 array = cls.fields();
5836 EXPECT(!array.IsNull());
5837 EXPECT(array.IsArray());
5838 array = cls.current_functions();
5839 EXPECT(!array.IsNull());
5840 EXPECT(array.IsArray());
5841}
5842
5843class ObjectAccumulator : public ObjectVisitor {
5844 public:
5845 explicit ObjectAccumulator(GrowableArray<Object*>* objects)
5846 : objects_(objects) {}
5847 virtual ~ObjectAccumulator() {}
5848 virtual void VisitObject(ObjectPtr obj) {
5849 if (obj->IsPseudoObject()) {
5850 return; // Cannot be wrapped in handles.
5851 }
5852 Object& handle = Object::Handle(obj);
5853 // Skip some common simple objects to run in reasonable time.
5854 if (handle.IsString() || handle.IsArray()) {
5855 return;
5856 }
5857 objects_->Add(&handle);
5858 }
5859
5860 private:
5861 GrowableArray<Object*>* objects_;
5862};
5863
5864ISOLATE_UNIT_TEST_CASE(ToCString) {
5865 // Set native resolvers in case we need to read native methods.
5866 {
5867 TransitionVMToNative transition(thread);
5872 }
5873
5875 GrowableArray<Object*> objects;
5876 {
5877 HeapIterationScope iteration(Thread::Current());
5878 ObjectAccumulator acc(&objects);
5879 iteration.IterateObjects(&acc);
5880 }
5881 for (intptr_t i = 0; i < objects.length(); ++i) {
5882 StackZone zone(thread);
5883 HANDLESCOPE(thread);
5884
5885 // All ToCString implementations should not allocate on the Dart heap so
5886 // they remain useful in all parts of the VM.
5887 NoSafepointScope no_safepoint;
5888 objects[i]->ToCString();
5889 }
5890}
5891
5892ISOLATE_UNIT_TEST_CASE(PrintJSON) {
5893 // Set native resolvers in case we need to read native methods.
5894 {
5895 TransitionVMToNative transition(thread);
5900 }
5901
5903 GrowableArray<Object*> objects;
5904 {
5906 ObjectAccumulator acc(&objects);
5907 iteration.IterateObjects(&acc);
5908 }
5909 for (intptr_t i = 0; i < objects.length(); ++i) {
5910 JSONStream js;
5911 objects[i]->PrintJSON(&js, false);
5912 EXPECT_SUBSTRING("\"type\":", js.ToCString());
5913 }
5914}
5915
5916ISOLATE_UNIT_TEST_CASE(PrintJSONPrimitives) {
5917 // WARNING: This MUST be big enough for the serialized JSON string.
5918 const int kBufferSize = 4096;
5919 char buffer[kBufferSize];
5920 Isolate* isolate = Isolate::Current();
5921
5922 // Class reference
5923 {
5924 JSONStream js;
5925 Class& cls = Class::Handle(isolate->group()->object_store()->bool_class());
5926 cls.PrintJSON(&js, true);
5927 const char* json_str = js.ToCString();
5928 ASSERT(strlen(json_str) < kBufferSize);
5929 ElideJSONSubstring("classes", json_str, buffer);
5930 ElideJSONSubstring("libraries", buffer, buffer);
5932
5933 EXPECT_STREQ(
5934 "{\"type\":\"@Class\",\"fixedId\":true,\"id\":\"\",\"name\":\"bool\","
5935 "\"location\":{\"type\":\"SourceLocation\",\"script\":{\"type\":\"@"
5936 "Script\","
5937 "\"fixedId\":true,\"id\":\"\",\"uri\":\"dart:core\\/bool.dart\","
5938 "\"_kind\":\"kernel\"}},"
5939 "\"library\":{\"type\":\"@Library\",\"fixedId\":true,\"id\":\"\","
5940 "\"name\":\"dart.core\",\"uri\":\"dart:core\"}}",
5941 buffer);
5942 }
5943 // Function reference
5944 {
5945 Thread* thread = Thread::Current();
5946 JSONStream js;
5947 Class& cls = Class::Handle(isolate->group()->object_store()->bool_class());
5948 const String& func_name = String::Handle(String::New("toString"));
5949 Function& func =
5951 ASSERT(!func.IsNull());
5952 func.PrintJSON(&js, true);
5953 const char* json_str = js.ToCString();
5954 ASSERT(strlen(json_str) < kBufferSize);
5955 ElideJSONSubstring("classes", json_str, buffer);
5956 ElideJSONSubstring("libraries", buffer, buffer);
5958 EXPECT_STREQ(
5959 "{\"type\":\"@Function\",\"fixedId\":true,\"id\":\"\","
5960 "\"name\":\"toString\",\"owner\":{\"type\":\"@Class\","
5961 "\"fixedId\":true,\"id\":\"\",\"name\":\"bool\","
5962 "\"location\":{\"type\":\"SourceLocation\","
5963 "\"script\":{\"type\":\"@Script\",\"fixedId\":true,"
5964 "\"id\":\"\",\"uri\":\"dart:core\\/bool.dart\","
5965 "\"_kind\":\"kernel\"}},"
5966 "\"library\":{\"type\":\"@Library\",\"fixedId\":true,\"id\":\"\","
5967 "\"name\":\"dart.core\",\"uri\":\"dart:core\"}},"
5968 "\"_kind\":\"RegularFunction\",\"static\":false,\"const\":false,"
5969 "\"implicit\":false,\"abstract\":false,"
5970 "\"_intrinsic\":false,\"_native\":false,\"isGetter\":false,"
5971 "\"isSetter\":false,\"location\":{\"type\":\"SourceLocation\","
5972 "\"script\":{\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\","
5973 "\"uri\":\"dart:core\\/bool.dart\",\"_kind\":\"kernel\"}}}",
5974 buffer);
5975 }
5976 // Library reference
5977 {
5978 JSONStream js;
5979 Library& lib =
5980 Library::Handle(isolate->group()->object_store()->core_library());
5981 lib.PrintJSON(&js, true);
5982 const char* json_str = js.ToCString();
5983 ASSERT(strlen(json_str) < kBufferSize);
5984 ElideJSONSubstring("libraries", json_str, buffer);
5985 EXPECT_STREQ(
5986 "{\"type\":\"@Library\",\"fixedId\":true,\"id\":\"\","
5987 "\"name\":\"dart.core\",\"uri\":\"dart:core\"}",
5988 buffer);
5989 }
5990 // Bool reference
5991 {
5992 JSONStream js;
5993 Bool::True().PrintJSON(&js, true);
5994 const char* json_str = js.ToCString();
5995 ASSERT(strlen(json_str) < kBufferSize);
5996 ElideJSONSubstring("classes", json_str, buffer);
5997 ElideJSONSubstring("libraries", buffer, buffer);
5999 EXPECT_STREQ(
6000 "{\"type\":\"@Instance\",\"_vmType\":\"Bool\",\"class\":{\"type\":\"@"
6001 "Class\",\"fixedId\":true,\"id\":\"\",\"name\":\"bool\",\"location\":{"
6002 "\"type\":\"SourceLocation\",\"script\":{\"type\":\"@Script\","
6003 "\"fixedId\":true,\"id\":\"\",\"uri\":\"dart:core\\/bool.dart\",\"_"
6004 "kind\":\"kernel\"}},\"library\":"
6005 "{\"type\":\"@Library\",\"fixedId\":true,\"id\":\"\",\"name\":\"dart."
6006 "core\",\"uri\":\"dart:core\"}},\"identityHashCode\":0,\"kind\":"
6007 "\"Bool\",\"fixedId\":true,\"id\":\"objects\\/bool-true\","
6008 "\"valueAsString\":\"true\"}",
6009 buffer);
6010 }
6011 // Smi reference
6012 {
6013 JSONStream js;
6014 const Integer& smi = Integer::Handle(Integer::New(7));
6015 smi.PrintJSON(&js, true);
6016 const char* json_str = js.ToCString();
6017 ASSERT(strlen(json_str) < kBufferSize);
6018 ElideJSONSubstring("classes", json_str, buffer);
6019 ElideJSONSubstring("_Smi@", buffer, buffer);
6020 ElideJSONSubstring("libraries", buffer, buffer);
6022 EXPECT_STREQ(
6023 "{\"type\":\"@Instance\",\"_vmType\":\"Smi\",\"class\":{\"type\":\"@"
6024 "Class\",\"fixedId\":true,\"id\":\"\",\"name\":\"_Smi\",\"_vmName\":"
6025 "\"\",\"location\":{\"type\":\"SourceLocation\",\"script\":{\"type\":"
6026 "\"@Script\",\"fixedId\":true,\"id\":\"\",\"uri\":\"dart:core-"
6027 "patch\\/integers.dart\",\"_kind\":\"kernel\"}"
6028 "},\"library\":{\"type\":\"@Library\",\"fixedId\":"
6029 "true,\"id\":\"\",\"name\":\"dart.core\",\"uri\":\"dart:core\"}},"
6030 "\"identityHashCode\":0,\"kind\":\"Int\",\"fixedId\":true,\"id\":"
6031 "\"objects\\/int-7\",\"valueAsString\":\"7\"}",
6032 buffer);
6033 }
6034 // Mint reference
6035 {
6036 JSONStream js;
6037 const Integer& smi = Integer::Handle(Integer::New(Mint::kMinValue));
6038 smi.PrintJSON(&js, true);
6039 const char* json_str = js.ToCString();
6040 ASSERT(strlen(json_str) < kBufferSize);
6041 ElideJSONSubstring("classes", json_str, buffer);
6042 ElideJSONSubstring("objects", buffer, buffer);
6043 ElideJSONSubstring("libraries", buffer, buffer);
6044 ElideJSONSubstring("_Mint@", buffer, buffer);
6046 EXPECT_STREQ(
6047 "{\"type\":\"@Instance\",\"_vmType\":\"Mint\",\"class\":{\"type\":\"@"
6048 "Class\",\"fixedId\":true,\"id\":\"\",\"name\":\"_Mint\",\"_vmName\":"
6049 "\"\",\"location\":{\"type\":\"SourceLocation\",\"script\":{\"type\":"
6050 "\"@Script\",\"fixedId\":true,\"id\":\"\",\"uri\":\"dart:core-"
6051 "patch\\/integers.dart\",\"_kind\":\"kernel\"}"
6052 "},\"library\":{\"type\":\"@Library\",\"fixedId\":"
6053 "true,\"id\":\"\",\"name\":\"dart.core\",\"uri\":\"dart:core\"}},"
6054 "\"identityHashCode\":0,\"id\":\"\",\"kind\":\"Int\",\"valueAsString\":"
6055 "\"-9223372036854775808\"}",
6056 buffer);
6057 }
6058 // Double reference
6059 {
6060 JSONStream js;
6061 const Double& dub = Double::Handle(Double::New(0.1234));
6062 dub.PrintJSON(&js, true);
6063 const char* json_str = js.ToCString();
6064 ASSERT(strlen(json_str) < kBufferSize);
6065 ElideJSONSubstring("classes", json_str, buffer);
6066 ElideJSONSubstring("objects", buffer, buffer);
6067 ElideJSONSubstring("libraries", buffer, buffer);
6068 ElideJSONSubstring("_Double@", buffer, buffer);
6070 EXPECT_STREQ(
6071 "{\"type\":\"@Instance\",\"_vmType\":\"Double\",\"class\":{\"type\":\"@"
6072 "Class\",\"fixedId\":true,\"id\":\"\",\"name\":\"_Double\",\"_vmName\":"
6073 "\"\",\"location\":{\"type\":\"SourceLocation\",\"script\":{\"type\":"
6074 "\"@Script\",\"fixedId\":true,\"id\":\"\",\"uri\":\"dart:core-"
6075 "patch\\/double.dart\",\"_kind\":\"kernel\"}"
6076 "},\"library\":{\"type\":\"@Library\",\"fixedId\":"
6077 "true,\"id\":\"\",\"name\":\"dart.core\",\"uri\":\"dart:core\"}},"
6078 "\"identityHashCode\":0,\"id\":\"\",\"kind\":\"Double\","
6079 "\"valueAsString\":\"0.1234\"}",
6080 buffer);
6081 }
6082 // String reference
6083 {
6084 JSONStream js;
6085 const String& str = String::Handle(String::New("dw"));
6086 str.PrintJSON(&js, true);
6087 const char* json_str = js.ToCString();
6088 ASSERT(strlen(json_str) < kBufferSize);
6089 ElideJSONSubstring("classes", json_str, buffer);
6090 ElideJSONSubstring("objects", buffer, buffer);
6091 ElideJSONSubstring("libraries", buffer, buffer);
6092 ElideJSONSubstring("_OneByteString@", buffer, buffer);
6094 EXPECT_STREQ(
6095 "{\"type\":\"@Instance\",\"_vmType\":\"String\",\"class\":{\"type\":\"@"
6096 "Class\",\"fixedId\":true,\"id\":\"\",\"name\":\"_OneByteString\",\"_"
6097 "vmName\":\"\",\"location\":{\"type\":\"SourceLocation\",\"script\":{"
6098 "\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\",\"uri\":\"dart:core-"
6099 "patch\\/string_patch.dart\",\"_kind\":\"kernel\"}"
6100 "},\"library\":{\"type\":\"@Library\",\"fixedId\":"
6101 "true,\"id\":\"\",\"name\":\"dart.core\",\"uri\":\"dart:core\"}},"
6102 "\"identityHashCode\":0,\"id\":\"\",\"kind\":\"String\",\"length\":2,"
6103 "\"valueAsString\":\"dw\"}",
6104 buffer);
6105 }
6106 // Array reference
6107 {
6108 JSONStream js;
6109 const Array& array = Array::Handle(Array::New(0));
6110 array.PrintJSON(&js, true);
6111 const char* json_str = js.ToCString();
6112 ASSERT(strlen(json_str) < kBufferSize);
6113 ElideJSONSubstring("classes", json_str, buffer);
6114 ElideJSONSubstring("objects", buffer, buffer);
6115 ElideJSONSubstring("libraries", buffer, buffer);
6116 ElideJSONSubstring("_List@", buffer, buffer);
6117 ElideJSONSubstring("_TypeParameter@", buffer, buffer);
6119 EXPECT_SUBSTRING(
6120 "{\"type\":\"@Instance\",\"_vmType\":\"Array\",\"class\":{\"type\":\"@"
6121 "Class\",\"fixedId\":true,\"id\":\"\",\"name\":\"_List\",\"_vmName\":"
6122 "\"\",\"location\":{\"type\":\"SourceLocation\",\"script\":{\"type\":"
6123 "\"@Script\",\"fixedId\":true,\"id\":\"\",\"uri\":\"dart:core-patch\\/"
6124 "array.dart\",\"_kind\":\"kernel\"}},"
6125 "\"library\":{\"type\":\"@Library\",\"fixedId\":true,\"id\":\"\","
6126 "\"name\":\"dart.core\",\"uri\":\"dart:core\"},\"typeParameters\":[{"
6127 "\"type\":\"@"
6128 "Instance\",\"_vmType\":\"TypeParameter\",\"class\":{\"type\":\"@"
6129 "Class\",\"fixedId\":true,\"id\":\"\",\"name\":\"_TypeParameter\",\"_"
6130 "vmName\":\"\",\"location\":{\"type\":"
6131 "\"SourceLocation\",\"script\":{\"type\":\"@Script\",\"fixedId\":true,"
6132 "\"id\":\"\",\"uri\":\"dart:core-patch\\/"
6133 "type_patch.dart\",\"_kind\":\"kernel\"}},"
6134 "\"library\":{\"type\":\"@Library\",\"fixedId\":"
6135 "true,\"id\":\"\",\"name\":\"dart.core\",\"uri\":\"dart:core\"}},"
6136 "\"identityHashCode\":",
6137 buffer);
6138
6139 EXPECT_SUBSTRING(
6140 "\"id\":\"\",\"kind\":\"TypeParameter\",\"name\":\"X0\","
6141 "\"parameterizedClass\":{\"type\":\"@Instance\",\"_vmType\":\"Class\","
6142 "\"class\":{\"type\":\"@Class\",\"fixedId\":true,\"id\":\"\",\"name\":"
6143 "\"Null\",\"location\":{\"type\":\"SourceLocation\",\"script\":{"
6144 "\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\",\"uri\":\"dart:"
6145 "core\\/"
6146 "null.dart\",\"_kind\":\"kernel\"}},"
6147 "\"library\":{\"type\":\"@Library\",\"fixedId\":true,\"id\":\"\","
6148 "\"name\":\"dart.core\",\"uri\":\"dart:core\"}},\"kind\":\"Null\","
6149 "\"fixedId\":true,\"id\":\"\",\"valueAsString\":\"null\"}}]},"
6150 "\"identityHashCode\":0,\"id\":\"\",\"kind\":\"List\",\"length\":0}",
6151 buffer);
6152 }
6153 OS::PrintErr("\n\n\n");
6154 // GrowableObjectArray reference
6155 {
6156 JSONStream js;
6157 const GrowableObjectArray& array =
6159 array.PrintJSON(&js, true);
6160 const char* json_str = js.ToCString();
6161 ASSERT(strlen(json_str) < kBufferSize);
6162 ElideJSONSubstring("classes", json_str, buffer);
6163 ElideJSONSubstring("objects", buffer, buffer);
6164 ElideJSONSubstring("libraries", buffer, buffer);
6165 ElideJSONSubstring("_GrowableList@", buffer, buffer);
6167 ElideJSONSubstring("_TypeParameter@", buffer, buffer);
6168 EXPECT_SUBSTRING(
6169 "{\"type\":\"@Instance\",\"_vmType\":\"GrowableObjectArray\",\"class\":"
6170 "{\"type\":\"@Class\",\"fixedId\":true,\"id\":\"\",\"name\":\"_"
6171 "GrowableList\",\"_vmName\":\"\",\"location\":{\"type\":"
6172 "\"SourceLocation\",\"script\":{\"type\":\"@Script\",\"fixedId\":true,"
6173 "\"id\":\"\",\"uri\":\"dart:core-patch\\/"
6174 "growable_array.dart\",\"_kind\":\"kernel\"}"
6175 "},\"library\":{\"type\":\"@Library\",\"fixedId\":"
6176 "true,\"id\":\"\",\"name\":\"dart.core\",\"uri\":\"dart:core\"},"
6177 "\"typeParameters\":[{\"type\":\"@Instance\",\"_vmType\":"
6178 "\"TypeParameter\",\"class\":{\"type\":\"@Class\",\"fixedId\":true,"
6179 "\"id\":\"\",\"name\":\"_TypeParameter\",\"_vmName\":\""
6180 "\",\"location\":{\"type\":\"SourceLocation\",\"script\":{"
6181 "\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\",\"uri\":\"dart:core-"
6182 "patch\\/"
6183 "type_patch.dart\",\"_kind\":\"kernel\"}"
6184 "},\"library\":{\"type\":\"@Library\",\"fixedId\":"
6185 "true,\"id\":\"\",\"name\":\"dart.core\",\"uri\":\"dart:core\"}},"
6186 "\"identityHashCode\":",
6187 buffer);
6188
6189 EXPECT_SUBSTRING(
6190 "\"id\":\"\",\"kind\":\"TypeParameter\",\"name\":\"X0\","
6191 "\"parameterizedClass\":{\"type\":\"@Instance\","
6192 "\"_vmType\":\"Class\",\"class\":{\"type\":\"@Class\",\"fixedId\":true,"
6193 "\"id\":\"\",\"name\":\"Null\",\"location\":{\"type\":"
6194 "\"SourceLocation\",\"script\":{\"type\":\"@Script\",\"fixedId\":true,"
6195 "\"id\":\"\",\"uri\":\"dart:core\\/"
6196 "null.dart\",\"_kind\":\"kernel\"}"
6197 "},\"library\":{\"type\":\"@Library\",\"fixedId\":true,\"id\":\"\","
6198 "\"name\":\"dart.core\",\"uri\":\"dart:core\"}},\"kind\":\"Null\","
6199 "\"fixedId\":true,\"id\":\"\",\"valueAsString\":\"null\"}}]},"
6200 "\"identityHashCode\":0,\"id\":\"\",\"kind\":\"List\",\"length\":0}",
6201 buffer);
6202 }
6203 // Map reference
6204 {
6205 JSONStream js;
6206 const Map& array = Map::Handle(Map::NewDefault());
6207 array.PrintJSON(&js, true);
6208 const char* json_str = js.ToCString();
6209 ASSERT(strlen(json_str) < kBufferSize);
6210 ElideJSONSubstring("classes", json_str, buffer);
6211 ElideJSONSubstring("objects", buffer, buffer);
6212 ElideJSONSubstring("libraries", buffer, buffer);
6213 ElideJSONSubstring("_Map@", buffer, buffer);
6215 ElideJSONSubstring("_TypeParameter@", buffer, buffer);
6216 EXPECT_SUBSTRING(
6217 "{\"type\":\"@Instance\",\"_vmType\":\"Map\",\"class\":{"
6218 "\"type\":\"@Class\",\"fixedId\":true,\"id\":\"\",\"name\":\"_"
6219 "Map\",\"_vmName\":\"\",\"location\":{\"type\":"
6220 "\"SourceLocation\",\"script\":{\"type\":\"@Script\",\"fixedId\":true,"
6221 "\"id\":\"\",\"uri\":\"dart:collection-patch\\/"
6222 "compact_hash.dart\",\"_kind\":\"kernel\"}"
6223 "},\"library\":{\"type\":\"@Library\",\"fixedId\":"
6224 "true,\"id\":\"\",\"name\":\"dart.collection\",\"uri\":\"dart:"
6225 "collection\"},\"typeParameters\":[{\"type\":\"@Instance\",\"_vmType\":"
6226 "\"TypeParameter\",\"class\":{\"type\":\"@Class\",\"fixedId\":true,"
6227 "\"id\":\"\",\"name\":\"_TypeParameter\",\"_vmName\":\""
6228 "\",\"location\":{\"type\":\"SourceLocation\",\"script\":{"
6229 "\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\",\"uri\":\"dart:core-"
6230 "patch\\/"
6231 "type_patch.dart\",\"_kind\":\"kernel\"}"
6232 "},\"library\":{\"type\":\"@Library\",\"fixedId\":"
6233 "true,\"id\":\"\",\"name\":\"dart.core\",\"uri\":\"dart:core\"}},"
6234 "\"identityHashCode\":",
6235 buffer);
6236
6237 EXPECT_SUBSTRING(
6238 "\"id\":\"\",\"kind\":\"TypeParameter\",\"name\":\"X0\","
6239 "\"parameterizedClass\":{\"type\":\"@Instance\","
6240 "\"_vmType\":\"Class\",\"class\":{\"type\":\"@Class\",\"fixedId\":true,"
6241 "\"id\":\"\",\"name\":\"Null\",\"location\":{\"type\":"
6242 "\"SourceLocation\",\"script\":{\"type\":\"@Script\",\"fixedId\":true,"
6243 "\"id\":\"\",\"uri\":\"dart:core\\/"
6244 "null.dart\",\"_kind\":\"kernel\"}"
6245 "},\"library\":{\"type\":\"@Library\",\"fixedId\":true,\"id\":\"\","
6246 "\"name\":\"dart.core\",\"uri\":\"dart:core\"}},\"kind\":\"Null\","
6247 "\"fixedId\":true,\"id\":\"\",\"valueAsString\":\"null\"}},{\"type\":"
6248 "\"@Instance\",\"_vmType\":\"TypeParameter\",\"class\":{\"type\":\"@"
6249 "Class\",\"fixedId\":true,\"id\":\"\",\"name\":\"_TypeParameter\",\"_"
6250 "vmName\":\"\",\"location\":{\"type\":"
6251 "\"SourceLocation\",\"script\":{\"type\":\"@Script\",\"fixedId\":true,"
6252 "\"id\":\"\",\"uri\":\"dart:core-patch\\/"
6253 "type_patch.dart\",\"_kind\":\"kernel\"}"
6254 "},\"library\":{\"type\":\"@Library\",\"fixedId\":"
6255 "true,\"id\":\"\",\"name\":\"dart.core\",\"uri\":\"dart:core\"}},"
6256 "\"identityHashCode\":",
6257 buffer);
6258
6259 EXPECT_SUBSTRING(
6260 "\"id\":\"\",\"kind\":\"TypeParameter\",\"name\":\"X1\","
6261 "\"parameterizedClass\":{\"type\":\"@Instance\","
6262 "\"_vmType\":\"Class\",\"class\":{\"type\":\"@Class\",\"fixedId\":true,"
6263 "\"id\":\"\",\"name\":\"Null\",\"location\":{\"type\":"
6264 "\"SourceLocation\",\"script\":{\"type\":\"@Script\",\"fixedId\":true,"
6265 "\"id\":\"\",\"uri\":\"dart:core\\/"
6266 "null.dart\",\"_kind\":\"kernel\"}"
6267 "},\"library\":{\"type\":\"@Library\",\"fixedId\":true,\"id\":\"\","
6268 "\"name\":\"dart.core\",\"uri\":\"dart:core\"}},\"kind\":\"Null\","
6269 "\"fixedId\":true,\"id\":\"\",\"valueAsString\":\"null\"}}]},"
6270 "\"identityHashCode\":0,\"id\":\"\",\"kind\":\"Map\",\"length\":0}",
6271 buffer);
6272 }
6273 // UserTag reference
6274 {
6275 JSONStream js;
6276 Instance& tag = Instance::Handle(isolate->default_tag());
6277 tag.PrintJSON(&js, true);
6278 const char* json_str = js.ToCString();
6279 ASSERT(strlen(json_str) < kBufferSize);
6280 ElideJSONSubstring("classes", json_str, buffer);
6281 ElideJSONSubstring("objects", buffer, buffer);
6282 ElideJSONSubstring("libraries", buffer, buffer);
6283 ElideJSONSubstring("_UserTag@", buffer, buffer);
6285 EXPECT_SUBSTRING(
6286 "\"type\":\"@Instance\",\"_vmType\":\"UserTag\",\"class\":{\"type\":\"@"
6287 "Class\",\"fixedId\":true,\"id\":\"\",\"name\":\"_UserTag\",\"_"
6288 "vmName\":\"\",\"location\":{\"type\":\"SourceLocation\",\"script\":{"
6289 "\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\",\"uri\":\"dart:"
6290 "developer-patch\\/"
6291 "profiler.dart\",\"_kind\":\"kernel\"}},\"library\":{\"type\":\"@"
6292 "Library\","
6293 "\"fixedId\":true,\"id\":\"\",\"name\":\"dart.developer\",\"uri\":"
6294 "\"dart:developer\"}},"
6295 // Handle non-zero identity hash.
6296 "\"identityHashCode\":",
6297 buffer);
6298 EXPECT_SUBSTRING(
6299 "\"id\":\"\","
6300 "\"kind\":\"UserTag\",\"label\":\"Default\"}",
6301 buffer);
6302 }
6303 // Type reference
6304 // TODO(turnidge): Add in all of the other Type siblings.
6305 {
6306 JSONStream js;
6307 Instance& type =
6308 Instance::Handle(isolate->group()->object_store()->bool_type());
6309 type.PrintJSON(&js, true);
6310 const char* json_str = js.ToCString();
6311 ASSERT(strlen(json_str) < kBufferSize);
6312 ElideJSONSubstring("classes", json_str, buffer);
6313 ElideJSONSubstring("objects", buffer, buffer);
6314 ElideJSONSubstring("libraries", buffer, buffer);
6315 ElideJSONSubstring("_Type@", buffer, buffer);
6317 EXPECT_SUBSTRING(
6318 "{\"type\":\"@Instance\",\"_vmType\":\"Type\",\"class\":{\"type\":\"@"
6319 "Class\",\"fixedId\":true,\"id\":\"\",\"name\":\"_Type\",\"_vmName\":"
6320 "\"\",\"location\":{\"type\":\"SourceLocation\",\"script\":{\"type\":"
6321 "\"@Script\",\"fixedId\":true,\"id\":\"\",\"uri\":\"dart:core-"
6322 "patch\\/type_patch.dart\",\"_kind\":\"kernel\"}"
6323 "},\"library\":{\"type\":\"@Library\",\"fixedId\":"
6324 "true,\"id\":\"\",\"name\":\"dart.core\",\"uri\":\"dart:core\"}},"
6325 // Handle non-zero identity hash.
6326 "\"identityHashCode\":",
6327 buffer);
6328 EXPECT_SUBSTRING(
6329 "\"kind\":\"Type\","
6330 "\"fixedId\":true,\"id\":\"\","
6331 "\"typeClass\":{\"type\":\"@Class\",\"fixedId\":true,\"id\":\"\","
6332 "\"name\":\"bool\",\"location\":{\"type\":\"SourceLocation\","
6333 "\"script\":{\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\",\"uri\":"
6334 "\"dart:core\\/bool.dart\",\"_kind\":\"kernel\"}"
6335 "},\"library\":{\"type\":\"@Library\",\"fixedId\":"
6336 "true,\"id\":\"\",\"name\":\"dart.core\",\"uri\":\"dart:core\"}},"
6337 "\"name\":\"bool\"}",
6338 buffer);
6339 }
6340 // Null reference
6341 {
6342 JSONStream js;
6343 Object::null_object().PrintJSON(&js, true);
6344 const char* json_str = js.ToCString();
6345 ASSERT(strlen(json_str) < kBufferSize);
6346 ElideJSONSubstring("classes", json_str, buffer);
6347 ElideJSONSubstring("libraries", buffer, buffer);
6349 EXPECT_STREQ(
6350 "{\"type\":\"@Instance\",\"_vmType\":\"null\",\"class\":{\"type\":\"@"
6351 "Class\",\"fixedId\":true,\"id\":\"\",\"name\":\"Null\",\"location\":{"
6352 "\"type\":\"SourceLocation\",\"script\":{\"type\":\"@Script\","
6353 "\"fixedId\":true,\"id\":\"\",\"uri\":\"dart:core\\/null.dart\",\"_"
6354 "kind\":\"kernel\"}},\"library\":"
6355 "{\"type\":\"@Library\",\"fixedId\":true,\"id\":\"\",\"name\":\"dart."
6356 "core\",\"uri\":\"dart:core\"}},\"kind\":\"Null\",\"fixedId\":true,"
6357 "\"id\":\"objects\\/null\",\"valueAsString\":\"null\"}",
6358 buffer);
6359 }
6360 // Sentinel reference
6361 {
6362 JSONStream js;
6363 Object::sentinel().PrintJSON(&js, true);
6364 EXPECT_STREQ(
6365 "{\"type\":\"Sentinel\","
6366 "\"kind\":\"NotInitialized\","
6367 "\"valueAsString\":\"<not initialized>\"}",
6368 js.ToCString());
6369 }
6370 // Transition sentinel reference
6371 {
6372 JSONStream js;
6373 Object::transition_sentinel().PrintJSON(&js, true);
6374 EXPECT_STREQ(
6375 "{\"type\":\"Sentinel\","
6376 "\"kind\":\"BeingInitialized\","
6377 "\"valueAsString\":\"<being initialized>\"}",
6378 js.ToCString());
6379 }
6380}
6381
6382#endif // !PRODUCT
6383
6384TEST_CASE(InstanceEquality) {
6385 // Test that Instance::OperatorEquals can call a user-defined operator==.
6386 const char* kScript =
6387 "class A {\n"
6388 " bool operator==(covariant A other) { return true; }\n"
6389 "}\n"
6390 "main() {\n"
6391 " A a = new A();\n"
6392 "}";
6393
6394 Dart_Handle h_lib = TestCase::LoadTestScript(kScript, nullptr);
6395 EXPECT_VALID(h_lib);
6396 Dart_Handle result = Dart_Invoke(h_lib, NewString("main"), 0, nullptr);
6398
6399 TransitionNativeToVM transition(thread);
6400 Library& lib = Library::Handle();
6401 lib ^= Api::UnwrapHandle(h_lib);
6402 const Class& clazz = Class::Handle(GetClass(lib, "A"));
6403 EXPECT(!clazz.IsNull());
6404 const Instance& a0 = Instance::Handle(Instance::New(clazz));
6405 const Instance& a1 = Instance::Handle(Instance::New(clazz));
6406 EXPECT(a0.ptr() != a1.ptr());
6407 EXPECT(a0.OperatorEquals(a0));
6408 EXPECT(a0.OperatorEquals(a1));
6409 EXPECT(a0.IsIdenticalTo(a0));
6410 EXPECT(!a0.IsIdenticalTo(a1));
6411}
6412
6413TEST_CASE(HashCode) {
6414 // Ensure C++ overrides of Instance::HashCode match the Dart implementations.
6415 const char* kScript =
6416 "foo() {\n"
6417 " return \"foo\".hashCode;\n"
6418 "}";
6419
6420 Dart_Handle h_lib = TestCase::LoadTestScript(kScript, nullptr);
6421 EXPECT_VALID(h_lib);
6422 Dart_Handle h_result = Dart_Invoke(h_lib, NewString("foo"), 0, nullptr);
6423 EXPECT_VALID(h_result);
6424
6425 TransitionNativeToVM transition(thread);
6427 result ^= Api::UnwrapHandle(h_result);
6428 String& foo = String::Handle(String::New("foo"));
6429 Integer& expected = Integer::Handle();
6430 expected ^= foo.HashCode();
6431 EXPECT(result.IsIdenticalTo(expected));
6433
6434const uint32_t kCalculateCanonicalizeHash = 0;
6435
6436// Checks that the .hashCode equals the VM CanonicalizeHash() for keys in
6437// constant maps.
6438//
6439// Expects a script with a method named `value`.
6440//
6441// If `hashcode_canonicalize_vm` is non-zero, the VM CanonicalizeHash()
6442// is not executed but the provided value is used.
6444 const char* value_script,
6445 uint32_t hashcode_canonicalize_vm = kCalculateCanonicalizeHash,
6446 bool check_identity = true,
6447 bool check_hashcode = true) {
6448 CStringUniquePtr kScriptChars(
6449 OS::SCreate(nullptr,
6450 "%s"
6451 "\n"
6452 "valueHashCode() {\n"
6453 " return value().hashCode;\n"
6454 "}\n"
6455 "\n"
6456 "valueIdentityHashCode() {\n"
6457 " return identityHashCode(value());\n"
6458 "}\n",
6459 value_script));
6460
6461 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars.get(), nullptr);
6462 EXPECT_VALID(lib);
6463 Dart_Handle value_result = Dart_Invoke(lib, NewString("value"), 0, nullptr);
6464 EXPECT_VALID(value_result);
6465 Dart_Handle hashcode_result;
6466 if (check_hashcode) {
6467 hashcode_result = Dart_Invoke(lib, NewString("valueHashCode"), 0, nullptr);
6468 EXPECT_VALID(hashcode_result);
6469 }
6470 Dart_Handle identity_hashcode_result =
6471 Dart_Invoke(lib, NewString("valueIdentityHashCode"), 0, nullptr);
6472 EXPECT_VALID(identity_hashcode_result);
6473
6474 TransitionNativeToVM transition(Thread::Current());
6475
6476 const auto& value_dart = Instance::CheckedHandle(
6477 Thread::Current()->zone(), Api::UnwrapHandle(value_result));
6478 int64_t hashcode_dart;
6479 if (check_hashcode) {
6480 hashcode_dart =
6481 Integer::Cast(Object::Handle(Api::UnwrapHandle(hashcode_result)))
6482 .AsInt64Value();
6483 }
6484 const int64_t identity_hashcode_dart =
6485 Integer::Cast(Object::Handle(Api::UnwrapHandle(identity_hashcode_result)))
6486 .AsInt64Value();
6487 if (hashcode_canonicalize_vm == 0) {
6488 hashcode_canonicalize_vm = Instance::Cast(value_dart).CanonicalizeHash();
6489 }
6490
6491 bool success = true;
6492
6493 if (check_hashcode) {
6494 success &= hashcode_dart == hashcode_canonicalize_vm;
6495 }
6496 if (check_identity) {
6497 success &= identity_hashcode_dart == hashcode_canonicalize_vm;
6498 }
6499
6500 if (!success) {
6501 LogBlock lb;
6502 THR_Print(
6503 "Dart hashCode or Dart identityHashCode does not equal VM "
6504 "CanonicalizeHash for %s\n",
6505 value_dart.ToCString());
6506 THR_Print("Dart hashCode %" Px64 " %" Pd64 "\n", hashcode_dart,
6507 hashcode_dart);
6508 THR_Print("Dart identityHashCode %" Px64 " %" Pd64 "\n",
6509 identity_hashcode_dart, identity_hashcode_dart);
6510 THR_Print("VM CanonicalizeHash %" Px32 " %" Pd32 "\n",
6511 hashcode_canonicalize_vm, hashcode_canonicalize_vm);
6512 }
6513
6514 return success;
6515}
6516
6517TEST_CASE(HashCode_Double) {
6518 const char* kScript =
6519 "value() {\n"
6520 " return 1.0;\n"
6521 "}\n";
6522 // Double VM CanonicalizeHash is not equal to hashCode, because doubles
6523 // cannot be used as keys in constant sets and maps. However, doubles
6524 // _can_ be used for lookups in which case they are equal to their integer
6525 // value.
6526 uint32_t kInt1HashCode = 0;
6527 {
6528 TransitionNativeToVM transition(thread);
6529 kInt1HashCode = Integer::Handle(Integer::New(1)).CanonicalizeHash();
6530 }
6531 EXPECT(HashCodeEqualsCanonicalizeHash(kScript, kInt1HashCode));
6532}
6533
6534TEST_CASE(HashCode_Mint) {
6535 const char* kScript =
6536 "value() {\n"
6537 " return 0x8000000;\n"
6538 "}\n";
6540}
6541
6542TEST_CASE(HashCode_Null) {
6543 const char* kScript =
6544 "value() {\n"
6545 " return null;\n"
6546 "}\n";
6548}
6549
6550TEST_CASE(HashCode_Smi) {
6551 const char* kScript =
6552 "value() {\n"
6553 " return 123;\n"
6554 "}\n";
6556}
6557
6558TEST_CASE(HashCode_String) {
6559 const char* kScript =
6560 "value() {\n"
6561 " return 'asdf';\n"
6562 "}\n";
6565
6566TEST_CASE(HashCode_Symbol) {
6567 const char* kScript =
6568 "value() {\n"
6569 " return #A;\n"
6570 "}\n";
6572 /*check_identity=*/false));
6573}
6574
6575TEST_CASE(HashCode_True) {
6576 const char* kScript =
6577 "value() {\n"
6578 " return true;\n"
6579 "}\n";
6581}
6582
6583TEST_CASE(HashCode_Type_Dynamic) {
6584 const char* kScript =
6585 "const type = dynamic;\n"
6586 "\n"
6587 "value() {\n"
6588 " return type;\n"
6589 "}\n";
6591 /*check_identity=*/false));
6592}
6593
6594TEST_CASE(HashCode_Type_Int) {
6595 const char* kScript =
6596 "const type = int;\n"
6597 "\n"
6598 "value() {\n"
6599 " return type;\n"
6600 "}\n";
6602 /*check_identity=*/false));
6603}
6604
6605TEST_CASE(Map_iteration) {
6606 const char* kScript =
6607 "makeMap() {\n"
6608 " var map = {'x': 3, 'y': 4, 'z': 5, 'w': 6};\n"
6609 " map.remove('y');\n"
6610 " map.remove('w');\n"
6611 " return map;\n"
6612 "}";
6613 Dart_Handle h_lib = TestCase::LoadTestScript(kScript, nullptr);
6614 EXPECT_VALID(h_lib);
6615 Dart_Handle h_result = Dart_Invoke(h_lib, NewString("makeMap"), 0, nullptr);
6616 EXPECT_VALID(h_result);
6617
6618 TransitionNativeToVM transition(thread);
6619 Instance& dart_map = Instance::Handle();
6620 dart_map ^= Api::UnwrapHandle(h_result);
6621 ASSERT(dart_map.IsMap());
6622 const Map& cc_map = Map::Cast(dart_map);
6623
6624 EXPECT_EQ(2, cc_map.Length());
6625
6626 Map::Iterator iterator(cc_map);
6627 Object& object = Object::Handle();
6628
6629 EXPECT(iterator.MoveNext());
6630 object = iterator.CurrentKey();
6631 EXPECT_STREQ("x", object.ToCString());
6632 object = iterator.CurrentValue();
6633 EXPECT_STREQ("3", object.ToCString());
6635 EXPECT(iterator.MoveNext());
6636 object = iterator.CurrentKey();
6637 EXPECT_STREQ("z", object.ToCString());
6638 object = iterator.CurrentValue();
6639 EXPECT_STREQ("5", object.ToCString());
6640
6641 EXPECT(!iterator.MoveNext());
6642}
6643
6644template <class LinkedHashBase>
6645static bool LinkedHashBaseEqual(const LinkedHashBase& map1,
6646 const LinkedHashBase& map2,
6647 bool print_diff,
6648 bool check_data = true) {
6649 if (check_data) {
6650 // Check data, only for non-nested.
6651 const auto& data1 = Array::Handle(map1.data());
6652 const auto& data2 = Array::Handle(map2.data());
6653 const intptr_t data1_length = Smi::Value(map1.used_data());
6654 const intptr_t data2_length = Smi::Value(map2.used_data());
6655 const bool data_length_equal = data1_length == data2_length;
6656 bool data_equal = data_length_equal;
6657 if (data_length_equal) {
6658 auto& object1 = Instance::Handle();
6659 auto& object2 = Instance::Handle();
6660 for (intptr_t i = 0; i < data1_length; i++) {
6661 object1 ^= data1.At(i);
6662 object2 ^= data2.At(i);
6663 data_equal &= object1.CanonicalizeEquals(object2);
6664 }
6665 }
6666 if (!data_equal) {
6667 if (print_diff) {
6668 THR_Print("LinkedHashBaseEqual Data not equal.\n");
6669 THR_Print("LinkedHashBaseEqual data1.length %" Pd " data1.length %" Pd
6670 " \n",
6671 data1_length, data2_length);
6672 auto& object1 = Instance::Handle();
6673 for (intptr_t i = 0; i < data1_length; i++) {
6674 object1 ^= data1.At(i);
6675 THR_Print("LinkedHashBaseEqual data1[%" Pd "] %s\n", i,
6676 object1.ToCString());
6677 }
6678 for (intptr_t i = 0; i < data2_length; i++) {
6679 object1 ^= data2.At(i);
6680 THR_Print("LinkedHashBaseEqual data2[%" Pd "] %s\n", i,
6681 object1.ToCString());
6682 }
6683 }
6684 return false;
6685 }
6686 }
6687
6688 // Check hashing.
6689 intptr_t hash_mask1 = Smi::Value(map1.hash_mask());
6690 EXPECT(!Integer::Handle(map2.hash_mask()).IsNull());
6691 intptr_t hash_mask2 = Smi::Value(map2.hash_mask());
6692 const bool hash_masks_equal = hash_mask1 == hash_mask2;
6693 if (!hash_masks_equal) {
6694 if (print_diff) {
6695 THR_Print("LinkedHashBaseEqual Hash masks not equal.\n");
6696 THR_Print("LinkedHashBaseEqual hash_mask1 %" Px " hash_mask2 %" Px " \n",
6697 hash_mask1, hash_mask2);
6698 }
6699 }
6700
6701 // Check indices.
6702 const auto& index1 = TypedData::Handle(map1.index());
6703 const auto& index2 = TypedData::Handle(map2.index());
6704 EXPECT(!index2.IsNull());
6705 ASSERT(index1.ElementType() == kUint32ArrayElement);
6706 ASSERT(index2.ElementType() == kUint32ArrayElement);
6707 const intptr_t kElementSize = 4;
6708 ASSERT(kElementSize == index1.ElementSizeInBytes());
6709 const bool index_length_equal = index1.Length() == index2.Length();
6710 bool index_equal = index_length_equal;
6711 if (index_length_equal) {
6712 for (intptr_t i = 0; i < index1.Length(); i++) {
6713 const uint32_t index1_val = index1.GetUint32(i * kElementSize);
6714 const uint32_t index2_val = index2.GetUint32(i * kElementSize);
6715 index_equal &= index1_val == index2_val;
6716 }
6717 }
6718 if (!index_equal && print_diff) {
6719 THR_Print("LinkedHashBaseEqual Indices not equal.\n");
6720 THR_Print("LinkedHashBaseEqual index1.length %" Pd " index2.length %" Pd
6721 " \n",
6722 index1.Length(), index2.Length());
6723 for (intptr_t i = 0; i < index1.Length(); i++) {
6724 const uint32_t index_val = index1.GetUint32(i * kElementSize);
6725 THR_Print("LinkedHashBaseEqual index1[%" Pd "] %" Px32 "\n", i,
6726 index_val);
6728 for (intptr_t i = 0; i < index2.Length(); i++) {
6729 const uint32_t index_val = index2.GetUint32(i * kElementSize);
6730 THR_Print("LinkedHashBaseEqual index2[%" Pd "] %" Px32 "\n", i,
6731 index_val);
6732 }
6733 }
6734 return index_equal;
6735}
6736
6737// Copies elements from data.
6738static MapPtr ConstructImmutableMap(const Array& input_data,
6739 intptr_t used_data,
6740 const TypeArguments& type_arguments) {
6742
6743 const auto& data = Array::Handle(Array::New(used_data));
6744 for (intptr_t i = 0; i < used_data; i++) {
6745 data.SetAt(i, Object::Handle(input_data.At(i)));
6746 }
6747 map.set_data(data);
6748 map.set_used_data(used_data);
6749 map.SetTypeArguments(type_arguments);
6750 map.set_deleted_keys(0);
6751 map.ComputeAndSetHashMask();
6752 map ^= map.Canonicalize(Thread::Current());
6753
6754 return map.ptr();
6755}
6756
6757// Constructs an immutable hashmap from a mutable one in this test.
6758TEST_CASE(ConstMap_vm) {
6759 const char* kScript = R"(
6760enum ExperimentalFlag {
6761 alternativeInvalidationStrategy,
6762 constFunctions,
6763 constantUpdate2018,
6764 constructorTearoffs,
6765 controlFlowCollections,
6766 extensionMethods,
6767 extensionTypes,
6768 genericMetadata,
6769 nonNullable,
6770 nonfunctionTypeAliases,
6771 setLiterals,
6772 spreadCollections,
6773 testExperiment,
6774 tripleShift,
6775 valueClass,
6776 variance,
6777}
6778
6779final Map<ExperimentalFlag?, bool> expiredExperimentalFlagsNonConst = {
6780 ExperimentalFlag.alternativeInvalidationStrategy: false,
6781 ExperimentalFlag.constFunctions: false,
6782 ExperimentalFlag.constantUpdate2018: true,
6783 ExperimentalFlag.constructorTearoffs: false,
6784 ExperimentalFlag.controlFlowCollections: true,
6785 ExperimentalFlag.extensionMethods: false,
6786 ExperimentalFlag.extensionTypes: false,
6787 ExperimentalFlag.genericMetadata: false,
6788 ExperimentalFlag.nonNullable: false,
6789 ExperimentalFlag.nonfunctionTypeAliases: false,
6790 ExperimentalFlag.setLiterals: true,
6791 ExperimentalFlag.spreadCollections: true,
6792 ExperimentalFlag.testExperiment: false,
6793 ExperimentalFlag.tripleShift: false,
6794 ExperimentalFlag.valueClass: false,
6795 ExperimentalFlag.variance: false,
6796};
6797
6798makeNonConstMap() {
6799 return expiredExperimentalFlagsNonConst;
6800}
6801
6802firstKey() {
6803 return ExperimentalFlag.alternativeInvalidationStrategy;
6804}
6805
6806firstKeyHashCode() {
6807 return firstKey().hashCode;
6808}
6809
6810firstKeyIdentityHashCode() {
6811 return identityHashCode(firstKey());
6812}
6813
6814bool lookupSpreadCollections(Map map) =>
6815 map[ExperimentalFlag.spreadCollections];
6816
6817bool? lookupNull(Map map) => map[null];
6818)";
6819 Dart_Handle lib = TestCase::LoadTestScript(kScript, nullptr);
6820 EXPECT_VALID(lib);
6821 Dart_Handle non_const_result =
6822 Dart_Invoke(lib, NewString("makeNonConstMap"), 0, nullptr);
6823 EXPECT_VALID(non_const_result);
6824 Dart_Handle first_key_result =
6825 Dart_Invoke(lib, NewString("firstKey"), 0, nullptr);
6826 EXPECT_VALID(first_key_result);
6827 Dart_Handle first_key_hashcode_result =
6828 Dart_Invoke(lib, NewString("firstKeyHashCode"), 0, nullptr);
6829 EXPECT_VALID(first_key_hashcode_result);
6830 Dart_Handle first_key_identity_hashcode_result =
6831 Dart_Invoke(lib, NewString("firstKeyIdentityHashCode"), 0, nullptr);
6832 EXPECT_VALID(first_key_identity_hashcode_result);
6833
6834 Dart_Handle const_argument;
6835
6836 {
6837 TransitionNativeToVM transition(thread);
6838 const auto& non_const_map =
6839 Map::Cast(Object::Handle(Api::UnwrapHandle(non_const_result)));
6840 const auto& non_const_type_args =
6841 TypeArguments::Handle(non_const_map.GetTypeArguments());
6842 const auto& non_const_data = Array::Handle(non_const_map.data());
6843 const auto& const_map = Map::Handle(ConstructImmutableMap(
6844 non_const_data, Smi::Value(non_const_map.used_data()),
6845 non_const_type_args));
6846 ASSERT(non_const_map.GetClassId() == kMapCid);
6847 ASSERT(const_map.GetClassId() == kConstMapCid);
6848 ASSERT(!non_const_map.IsCanonical());
6849 ASSERT(const_map.IsCanonical());
6850
6851 const_argument = Api::NewHandle(thread, const_map.ptr());
6852 }
6853
6854 Dart_Handle lookup_result = Dart_Invoke(
6855 lib, NewString("lookupSpreadCollections"), 1, &const_argument);
6856 EXPECT_VALID(lookup_result);
6857 EXPECT_TRUE(lookup_result);
6858
6859 Dart_Handle lookup_null_result =
6860 Dart_Invoke(lib, NewString("lookupNull"), 1, &const_argument);
6861 EXPECT_VALID(lookup_null_result);
6862 EXPECT_NULL(lookup_null_result);
6863
6864 {
6865 TransitionNativeToVM transition(thread);
6866 const auto& non_const_object =
6867 Object::Handle(Api::UnwrapHandle(non_const_result));
6868 const auto& non_const_map = Map::Cast(non_const_object);
6869 const auto& const_object =
6871 const auto& const_map = Map::Cast(const_object);
6872
6873 EXPECT(non_const_map.GetClassId() != const_map.GetClassId());
6874
6875 // Check that the index is identical.
6876 EXPECT(LinkedHashBaseEqual(non_const_map, const_map,
6877 /*print_diff=*/true));
6878 }
6880
6881static bool IsLinkedHashBase(const Object& object) {
6882 return object.IsMap() || object.IsSet();
6883}
6884
6885// Checks that the non-constant and constant HashMap and HashSets are equal.
6886//
6887// Expects a script with a methods named `nonConstValue`, `constValue`, and
6888// `init`.
6889template <class LinkedHashBase, int kMutableCid, int kImmutableCid>
6890static void HashBaseNonConstEqualsConst(const char* script,
6891 bool check_data = true) {
6893 EXPECT_VALID(lib);
6894 Dart_Handle init_result = Dart_Invoke(lib, NewString("init"), 0, nullptr);
6895 EXPECT_VALID(init_result);
6896 Dart_Handle non_const_result =
6897 Dart_Invoke(lib, NewString("nonConstValue"), 0, nullptr);
6898 EXPECT_VALID(non_const_result);
6899 Dart_Handle const_result =
6900 Dart_Invoke(lib, NewString("constValue"), 0, nullptr);
6901 EXPECT_VALID(const_result);
6902
6903 TransitionNativeToVM transition(Thread::Current());
6904 const auto& non_const_object =
6905 Object::Handle(Api::UnwrapHandle(non_const_result));
6906 const auto& const_object = Object::Handle(Api::UnwrapHandle(const_result));
6907 non_const_object.IsMap();
6908 EXPECT(IsLinkedHashBase(non_const_object));
6909 if (!IsLinkedHashBase(non_const_object)) return;
6910 const auto& non_const_value = LinkedHashBase::Cast(non_const_object);
6911 EXPECT(IsLinkedHashBase(const_object));
6912 if (!IsLinkedHashBase(const_object)) return;
6913 const auto& const_value = LinkedHashBase::Cast(const_object);
6914 EXPECT_EQ(non_const_value.GetClassId(), kMutableCid);
6915 EXPECT_EQ(const_value.GetClassId(), kImmutableCid);
6916 EXPECT(!non_const_value.IsCanonical());
6917 EXPECT(const_value.IsCanonical());
6918 EXPECT(LinkedHashBaseEqual(non_const_value, const_value,
6919 /*print_diff=*/true, check_data));
6920}
6922static void HashMapNonConstEqualsConst(const char* script,
6923 bool check_data = true) {
6924 HashBaseNonConstEqualsConst<Map, kMapCid, kConstMapCid>(script, check_data);
6925}
6926
6927static void HashSetNonConstEqualsConst(const char* script,
6928 bool check_data = true) {
6929 HashBaseNonConstEqualsConst<Set, kSetCid, kConstSetCid>(script, check_data);
6930}
6931
6932TEST_CASE(ConstMap_small) {
6933 const char* kScript = R"(
6934constValue() => const {1: 42, 'foo': 499, 2: 'bar'};
6935
6936nonConstValue() => {1: 42, 'foo': 499, 2: 'bar'};
6937
6938void init() {
6939 constValue()[null];
6940}
6941)";
6943}
6944
6945TEST_CASE(ConstMap_null) {
6946 const char* kScript = R"(
6947constValue() => const {1: 42, 'foo': 499, null: 'bar'};
6948
6949nonConstValue() => {1: 42, 'foo': 499, null: 'bar'};
6950
6951void init() {
6952 constValue()[null];
6953}
6954)";
6956}
6957
6958TEST_CASE(ConstMap_larger) {
6959 const char* kScript = R"(
6960enum ExperimentalFlag {
6961 alternativeInvalidationStrategy,
6962 constFunctions,
6963 constantUpdate2018,
6964 constructorTearoffs,
6965 controlFlowCollections,
6966 extensionMethods,
6967 extensionTypes,
6968 genericMetadata,
6969 nonNullable,
6970 nonfunctionTypeAliases,
6971 setLiterals,
6972 spreadCollections,
6973 testExperiment,
6974 tripleShift,
6975 valueClass,
6976 variance,
6977}
6978
6979const Map<ExperimentalFlag, bool> expiredExperimentalFlags = {
6980 ExperimentalFlag.alternativeInvalidationStrategy: false,
6981 ExperimentalFlag.constFunctions: false,
6982 ExperimentalFlag.constantUpdate2018: true,
6983 ExperimentalFlag.constructorTearoffs: false,
6984 ExperimentalFlag.controlFlowCollections: true,
6985 ExperimentalFlag.extensionMethods: false,
6986 ExperimentalFlag.extensionTypes: false,
6987 ExperimentalFlag.genericMetadata: false,
6988 ExperimentalFlag.nonNullable: false,
6989 ExperimentalFlag.nonfunctionTypeAliases: false,
6990 ExperimentalFlag.setLiterals: true,
6991 ExperimentalFlag.spreadCollections: true,
6992 ExperimentalFlag.testExperiment: false,
6993 ExperimentalFlag.tripleShift: false,
6994 ExperimentalFlag.valueClass: false,
6995 ExperimentalFlag.variance: false,
6996};
6997
6998final Map<ExperimentalFlag, bool> expiredExperimentalFlagsNonConst = {
6999 ExperimentalFlag.alternativeInvalidationStrategy: false,
7000 ExperimentalFlag.constFunctions: false,
7001 ExperimentalFlag.constantUpdate2018: true,
7002 ExperimentalFlag.constructorTearoffs: false,
7003 ExperimentalFlag.controlFlowCollections: true,
7004 ExperimentalFlag.extensionMethods: false,
7005 ExperimentalFlag.extensionTypes: false,
7006 ExperimentalFlag.genericMetadata: false,
7007 ExperimentalFlag.nonNullable: false,
7008 ExperimentalFlag.nonfunctionTypeAliases: false,
7009 ExperimentalFlag.setLiterals: true,
7010 ExperimentalFlag.spreadCollections: true,
7011 ExperimentalFlag.testExperiment: false,
7012 ExperimentalFlag.tripleShift: false,
7013 ExperimentalFlag.valueClass: false,
7014 ExperimentalFlag.variance: false,
7015};
7016
7017constValue() => expiredExperimentalFlags;
7018
7019nonConstValue() => expiredExperimentalFlagsNonConst;
7020
7021void init() {
7022 constValue()[null];
7023}
7024)";
7026}
7027
7028TEST_CASE(ConstMap_nested) {
7029 const char* kScript = R"(
7030enum Abi {
7031 wordSize64,
7032 wordSize32Align32,
7033 wordSize32Align64,
7034}
7035
7036enum NativeType {
7037 kNativeType,
7038 kNativeInteger,
7039 kNativeDouble,
7040 kPointer,
7041 kNativeFunction,
7042 kInt8,
7043 kInt16,
7044 kInt32,
7045 kInt64,
7046 kUint8,
7047 kUint16,
7048 kUint32,
7049 kUint64,
7050 kIntptr,
7051 kFloat,
7052 kDouble,
7053 kVoid,
7054 kOpaque,
7055 kStruct,
7056 kHandle,
7057}
7058
7059const nonSizeAlignment = <Abi, Map<NativeType, int>>{
7060 Abi.wordSize64: {},
7061 Abi.wordSize32Align32: {
7062 NativeType.kDouble: 4,
7063 NativeType.kInt64: 4,
7064 NativeType.kUint64: 4
7065 },
7066 Abi.wordSize32Align64: {},
7067};
7068
7069final nonSizeAlignmentNonConst = <Abi, Map<NativeType, int>>{
7070 Abi.wordSize64: {},
7071 Abi.wordSize32Align32: {
7072 NativeType.kDouble: 4,
7073 NativeType.kInt64: 4,
7074 NativeType.kUint64: 4
7075 },
7076 Abi.wordSize32Align64: {},
7077};
7078
7079constValue() => nonSizeAlignment;
7080
7081nonConstValue() => nonSizeAlignmentNonConst;
7082
7083void init() {
7084 constValue()[null];
7085}
7086)";
7087 HashMapNonConstEqualsConst(kScript, false);
7088}
7089
7090TEST_CASE(Set_iteration) {
7091 const char* kScript = R"(
7092makeSet() {
7093 var set = {'x', 'y', 'z', 'w'};
7094 set.remove('y');
7095 set.remove('w');
7096 return set;
7097}
7098)";
7099 Dart_Handle h_lib = TestCase::LoadTestScript(kScript, nullptr);
7100 EXPECT_VALID(h_lib);
7101 Dart_Handle h_result = Dart_Invoke(h_lib, NewString("makeSet"), 0, nullptr);
7102 EXPECT_VALID(h_result);
7103
7104 TransitionNativeToVM transition(thread);
7105 Instance& dart_set = Instance::Handle();
7106 dart_set ^= Api::UnwrapHandle(h_result);
7107 ASSERT(dart_set.IsSet());
7108 const Set& cc_set = Set::Cast(dart_set);
7109
7110 EXPECT_EQ(2, cc_set.Length());
7111
7112 Set::Iterator iterator(cc_set);
7113 Object& object = Object::Handle();
7114
7115 EXPECT(iterator.MoveNext());
7116 object = iterator.CurrentKey();
7117 EXPECT_STREQ("x", object.ToCString());
7118
7119 EXPECT(iterator.MoveNext());
7120 object = iterator.CurrentKey();
7121 EXPECT_STREQ("z", object.ToCString());
7122
7123 EXPECT(!iterator.MoveNext());
7124}
7125
7126// Copies elements from data.
7127static SetPtr ConstructImmutableSet(const Array& input_data,
7128 intptr_t used_data,
7129 const TypeArguments& type_arguments) {
7131
7132 const auto& data = Array::Handle(Array::New(used_data));
7133 for (intptr_t i = 0; i < used_data; i++) {
7134 data.SetAt(i, Object::Handle(input_data.At(i)));
7136 set.set_data(data);
7137 set.set_used_data(used_data);
7138 set.SetTypeArguments(type_arguments);
7139 set.set_deleted_keys(0);
7140 set.ComputeAndSetHashMask();
7141 set ^= set.Canonicalize(Thread::Current());
7142
7143 return set.ptr();
7144}
7145
7146TEST_CASE(ConstSet_vm) {
7147 const char* kScript = R"(
7148makeNonConstSet() {
7149 return {1, 2, 3, 5, 8, 13};
7150}
7151
7152bool containsFive(Set set) => set.contains(5);
7153)";
7154 Dart_Handle lib = TestCase::LoadTestScript(kScript, nullptr);
7155 EXPECT_VALID(lib);
7156 Dart_Handle non_const_result =
7157 Dart_Invoke(lib, NewString("makeNonConstSet"), 0, nullptr);
7158 EXPECT_VALID(non_const_result);
7159
7160 Dart_Handle const_argument;
7161
7162 {
7163 TransitionNativeToVM transition(thread);
7164 const auto& non_const_object =
7165 Object::Handle(Api::UnwrapHandle(non_const_result));
7166 const auto& non_const_set = Set::Cast(non_const_object);
7167 ASSERT(non_const_set.GetClassId() == kSetCid);
7168 ASSERT(!non_const_set.IsCanonical());
7169
7170 const auto& non_const_data = Array::Handle(non_const_set.data());
7171 const auto& non_const_type_args =
7172 TypeArguments::Handle(non_const_set.GetTypeArguments());
7173 const auto& const_set = Set::Handle(ConstructImmutableSet(
7174 non_const_data, Smi::Value(non_const_set.used_data()),
7175 non_const_type_args));
7176 ASSERT(const_set.GetClassId() == kConstSetCid);
7177 ASSERT(const_set.IsCanonical());
7178
7179 const_argument = Api::NewHandle(thread, const_set.ptr());
7180 }
7181
7182 Dart_Handle contains_5_result =
7183 Dart_Invoke(lib, NewString("containsFive"), 1, &const_argument);
7184 EXPECT_VALID(contains_5_result);
7185 EXPECT_TRUE(contains_5_result);
7186
7187 {
7188 TransitionNativeToVM transition(thread);
7189 const auto& non_const_object =
7190 Object::Handle(Api::UnwrapHandle(non_const_result));
7191 const auto& non_const_set = Set::Cast(non_const_object);
7192 const auto& const_object =
7194 const auto& const_set = Set::Cast(const_object);
7195
7196 EXPECT(non_const_set.GetClassId() != const_set.GetClassId());
7197
7198 // Check that the index is identical.
7199 EXPECT(LinkedHashBaseEqual(non_const_set, const_set,
7200 /*print_diff=*/true));
7201 }
7202}
7203
7204TEST_CASE(ConstSet_small) {
7205 const char* kScript = R"(
7206constValue() => const {1, 2, 3, 5, 8, 13};
7207
7208nonConstValue() => {1, 2, 3, 5, 8, 13};
7209
7210void init() {
7211 constValue().contains(null);
7212}
7213)";
7215}
7216
7217TEST_CASE(ConstSet_larger) {
7218 const char* kScript = R"(
7219const Set<String> tokensThatMayFollowTypeArg = {
7220 '(',
7221 ')',
7222 ']',
7223 '}',
7224 ':',
7225 ';',
7226 ',',
7227 '.',
7228 '?',
7229 '==',
7230 '!=',
7231 '..',
7232 '?.',
7233 '\?\?',
7234 '?..',
7235 '&',
7236 '|',
7237 '^',
7238 '+',
7239 '*',
7240 '%',
7241 '/',
7242 '~/'
7243};
7244
7245final Set<String> tokensThatMayFollowTypeArgNonConst = {
7246 '(',
7247 ')',
7248 ']',
7249 '}',
7250 ':',
7251 ';',
7252 ',',
7253 '.',
7254 '?',
7255 '==',
7256 '!=',
7257 '..',
7258 '?.',
7259 '\?\?',
7260 '?..',
7261 '&',
7262 '|',
7263 '^',
7264 '+',
7265 '*',
7266 '%',
7267 '/',
7268 '~/'
7269};
7270
7271constValue() => tokensThatMayFollowTypeArg;
7272
7273nonConstValue() => tokensThatMayFollowTypeArgNonConst;
7274
7275void init() {
7276 constValue().contains(null);
7277}
7278)";
7280}
7281
7282static void CheckConcatAll(const String* data[], intptr_t n) {
7283 Thread* thread = Thread::Current();
7284 Zone* zone = thread->zone();
7285 GrowableHandlePtrArray<const String> pieces(zone, n);
7286 const Array& array = Array::Handle(zone, Array::New(n));
7287 for (int i = 0; i < n; i++) {
7288 pieces.Add(*data[i]);
7289 array.SetAt(i, *data[i]);
7290 }
7291 const String& res1 =
7292 String::Handle(zone, Symbols::FromConcatAll(thread, pieces));
7293 const String& res2 = String::Handle(zone, String::ConcatAll(array));
7294 EXPECT(res1.Equals(res2));
7295}
7296
7297ISOLATE_UNIT_TEST_CASE(Symbols_FromConcatAll) {
7298 {
7299 const String* data[3] = {&Symbols::TypeError(), &Symbols::Dot(),
7300 &Symbols::isPaused()};
7301 CheckConcatAll(data, 3);
7302 }
7303
7304 {
7305 const intptr_t kWideCharsLen = 7;
7306 uint16_t wide_chars[kWideCharsLen] = {'H', 'e', 'l', 'l', 'o', 256, '!'};
7307 const String& two_str =
7308 String::Handle(String::FromUTF16(wide_chars, kWideCharsLen));
7309
7310 const String* data[3] = {&two_str, &Symbols::Dot(), &two_str};
7314 {
7315 const String& empty = String::Handle(String::New(""));
7316 const String* data[3] = {&Symbols::TypeError(), &empty,
7317 &Symbols::isPaused()};
7318 CheckConcatAll(data, 3);
7319 }
7320}
7321
7322struct TestResult {
7323 const char* in;
7324 const char* out;
7325};
7326
7327ISOLATE_UNIT_TEST_CASE(String_ScrubName) {
7328 TestResult tests[] = {
7329 {"(dynamic, dynamic) => void", "(dynamic, dynamic) => void"},
7330 {"_List@915557746", "_List"},
7331 {"_HashMap@600006304<K, V>(dynamic) => V",
7332 "_HashMap<K, V>(dynamic) => V"},
7333 {"set:foo", "foo="},
7334 {"get:foo", "foo"},
7335 {"_ReceivePortImpl@709387912", "_ReceivePortImpl"},
7336 {"_ReceivePortImpl@709387912._internal@709387912",
7337 "_ReceivePortImpl._internal"},
7338 {"_C@6328321&_E@6328321&_F@6328321", "_C&_E&_F"},
7339 {"List.", "List"},
7340 {"get:foo@6328321", "foo"},
7341 {"_MyClass@6328321.", "_MyClass"},
7342 {"_MyClass@6328321.named", "_MyClass.named"},
7343 };
7344 String& test = String::Handle();
7345 const char* result;
7346 for (size_t i = 0; i < ARRAY_SIZE(tests); i++) {
7347 test = String::New(tests[i].in);
7349 EXPECT_STREQ(tests[i].out, result);
7350 }
7351}
7352
7353ISOLATE_UNIT_TEST_CASE(String_EqualsUTF32) {
7354 // Regression test for Issue 27433. Checks that comparisons between Strings
7355 // and utf32 arrays happens after conversion to utf16 instead of utf32, as
7356 // required for proper canonicalization of string literals with a lossy
7357 // utf32->utf16 conversion.
7358 int32_t char_codes[] = {0, 0x0a, 0x0d, 0x7f, 0xff,
7359 0xffff, 0xd800, 0xdc00, 0xdbff, 0xdfff};
7360
7361 const String& str =
7362 String::Handle(String::FromUTF32(char_codes, ARRAY_SIZE(char_codes)));
7363 EXPECT(str.Equals(char_codes, ARRAY_SIZE(char_codes)));
7364}
7365
7366TEST_CASE(TypeParameterTypeRef) {
7367 // Regression test for issue 82890.
7368 const char* kScriptChars =
7369 "void foo<T extends C<T>>(T x) {}\n"
7370 "void bar<M extends U<M>>(M x) {}\n"
7371 "abstract class C<T> {}\n"
7372 "abstract class U<T> extends C<T> {}\n";
7373 TestCase::LoadTestScript(kScriptChars, nullptr);
7374 TransitionNativeToVM transition(thread);
7377 const Library& lib = Library::Handle(Library::LookupLibrary(thread, name));
7378 EXPECT(!lib.IsNull());
7379
7380 const Function& foo = Function::Handle(GetFunction(lib, "foo"));
7381 const Function& bar = Function::Handle(GetFunction(lib, "bar"));
7384 EXPECT(!m.IsSubtypeOf(t, Heap::kNew));
7385}
7386
7387static void FinalizeAndCanonicalize(AbstractType* type) {
7389 ASSERT(type->IsCanonical());
7390}
7391
7392static void CheckSubtypeRelation(const Expect& expect,
7393 const AbstractType& sub,
7394 const AbstractType& super,
7395 bool is_subtype) {
7396 if (sub.IsSubtypeOf(super, Heap::kNew) != is_subtype) {
7397 TextBuffer buffer(128);
7398 buffer.AddString("Expected ");
7399 sub.PrintName(Object::kScrubbedName, &buffer);
7400 buffer.Printf(" to %s a subtype of ", is_subtype ? "be" : "not be");
7401 super.PrintName(Object::kScrubbedName, &buffer);
7402 expect.Fail("%s", buffer.buffer());
7403 }
7404}
7405
7406#define EXPECT_SUBTYPE(sub, super) \
7407 CheckSubtypeRelation(Expect(__FILE__, __LINE__), sub, super, true);
7408#define EXPECT_NOT_SUBTYPE(sub, super) \
7409 CheckSubtypeRelation(Expect(__FILE__, __LINE__), sub, super, false);
7410
7411ISOLATE_UNIT_TEST_CASE(ClosureType_SubtypeOfFunctionType) {
7412 const auto& closure_class =
7413 Class::Handle(IsolateGroup::Current()->object_store()->closure_class());
7414 const auto& closure_type = Type::Handle(closure_class.DeclarationType());
7415 auto& closure_type_nullable = Type::Handle(
7416 closure_type.ToNullability(Nullability::kNullable, Heap::kNew));
7417 FinalizeAndCanonicalize(&closure_type_nullable);
7418 auto& closure_type_nonnullable = Type::Handle(
7419 closure_type.ToNullability(Nullability::kNonNullable, Heap::kNew));
7420 FinalizeAndCanonicalize(&closure_type_nonnullable);
7421
7422 const auto& function_type =
7423 Type::Handle(IsolateGroup::Current()->object_store()->function_type());
7424 auto& function_type_nullable = Type::Handle(
7425 function_type.ToNullability(Nullability::kNullable, Heap::kNew));
7426 FinalizeAndCanonicalize(&function_type_nullable);
7427 auto& function_type_nonnullable = Type::Handle(
7428 function_type.ToNullability(Nullability::kNonNullable, Heap::kNew));
7429 FinalizeAndCanonicalize(&function_type_nonnullable);
7430
7431 EXPECT_SUBTYPE(closure_type_nonnullable, function_type_nullable);
7432 EXPECT_SUBTYPE(closure_type_nonnullable, function_type_nonnullable);
7433 EXPECT_SUBTYPE(closure_type_nullable, function_type_nullable);
7434 EXPECT_NOT_SUBTYPE(closure_type_nullable, function_type_nonnullable);
7435
7436 const auto& async_lib = Library::Handle(Library::AsyncLibrary());
7437 const auto& future_or_class =
7438 Class::Handle(async_lib.LookupClass(Symbols::FutureOr()));
7439 auto& tav_function_nullable = TypeArguments::Handle(TypeArguments::New(1));
7440 tav_function_nullable.SetTypeAt(0, function_type_nullable);
7441 tav_function_nullable = tav_function_nullable.Canonicalize(thread);
7442 auto& tav_function_nonnullable = TypeArguments::Handle(TypeArguments::New(1));
7443 tav_function_nonnullable.SetTypeAt(0, function_type_nonnullable);
7444 tav_function_nonnullable = tav_function_nonnullable.Canonicalize(thread);
7445
7446 auto& future_or_function_type_nullable =
7447 Type::Handle(Type::New(future_or_class, tav_function_nullable));
7448 FinalizeAndCanonicalize(&future_or_function_type_nullable);
7449 auto& future_or_function_type_nonnullable =
7450 Type::Handle(Type::New(future_or_class, tav_function_nonnullable));
7451 FinalizeAndCanonicalize(&future_or_function_type_nonnullable);
7452
7453 EXPECT_SUBTYPE(closure_type_nonnullable, future_or_function_type_nullable);
7454 EXPECT_SUBTYPE(closure_type_nonnullable, future_or_function_type_nonnullable);
7455 EXPECT_SUBTYPE(closure_type_nullable, future_or_function_type_nullable);
7456 EXPECT_NOT_SUBTYPE(closure_type_nullable,
7457 future_or_function_type_nonnullable);
7458}
7459
7460ISOLATE_UNIT_TEST_CASE(FunctionType_IsSubtypeOfNonNullableObject) {
7461 const auto& type_object = Type::Handle(
7462 IsolateGroup::Current()->object_store()->non_nullable_object_type());
7463
7464 auto& type_function_int_nullary =
7466 type_function_int_nullary.set_result_type(Type::Handle(Type::IntType()));
7467 FinalizeAndCanonicalize(&type_function_int_nullary);
7468
7469 auto& type_nullable_function_int_nullary =
7470 FunctionType::Handle(type_function_int_nullary.ToNullability(
7472 FinalizeAndCanonicalize(&type_nullable_function_int_nullary);
7473
7474 EXPECT_SUBTYPE(type_function_int_nullary, type_object);
7475 EXPECT_NOT_SUBTYPE(type_nullable_function_int_nullary, type_object);
7476}
7477
7478#undef EXPECT_NOT_SUBTYPE
7479#undef EXPECT_SUBTYPE
7480
7481static void ExpectTypesEquivalent(const Expect& expect,
7482 const AbstractType& expected,
7483 const AbstractType& got,
7484 TypeEquality kind) {
7485 if (got.IsEquivalent(expected, kind)) return;
7486 TextBuffer buffer(128);
7487 buffer.AddString("Expected type ");
7488 expected.PrintName(Object::kScrubbedName, &buffer);
7489 buffer.AddString(", got ");
7490 got.PrintName(Object::kScrubbedName, &buffer);
7491 expect.Fail("%s", buffer.buffer());
7492}
7493
7494#define EXPECT_TYPES_EQUAL(expected, got) \
7495 ExpectTypesEquivalent(Expect(__FILE__, __LINE__), expected, got, \
7496 TypeEquality::kCanonical);
7497
7498TEST_CASE(Class_GetInstantiationOf) {
7499 const char* kScript = R"(
7500 class B<T> {}
7501 class A1<X, Y> implements B<List<Y>> {}
7502 class A2<X, Y> extends A1<Y, X> {}
7503 )";
7504 Dart_Handle api_lib = TestCase::LoadTestScript(kScript, nullptr);
7505 EXPECT_VALID(api_lib);
7506 TransitionNativeToVM transition(thread);
7507 Zone* const zone = thread->zone();
7508
7509 const auto& root_lib =
7510 Library::CheckedHandle(zone, Api::UnwrapHandle(api_lib));
7511 EXPECT(!root_lib.IsNull());
7512 const auto& class_b = Class::Handle(zone, GetClass(root_lib, "B"));
7513 const auto& class_a1 = Class::Handle(zone, GetClass(root_lib, "A1"));
7514 const auto& class_a2 = Class::Handle(zone, GetClass(root_lib, "A2"));
7515
7516 const auto& core_lib = Library::Handle(zone, Library::CoreLibrary());
7517 const auto& class_list = Class::Handle(zone, GetClass(core_lib, "List"));
7518
7519 const auto& decl_type_b = Type::Handle(zone, class_b.DeclarationType());
7520 const auto& decl_type_list = Type::Handle(zone, class_list.DeclarationType());
7521 const auto& null_tav = Object::null_type_arguments();
7522
7523 // Test that A1.GetInstantiationOf(B) returns B<List<A1::Y>>.
7524 {
7525 const auto& decl_type_a1 = Type::Handle(zone, class_a1.DeclarationType());
7526 const auto& decl_type_args_a1 =
7527 TypeArguments::Handle(zone, decl_type_a1.arguments());
7528 const auto& type_arg_a1_y =
7529 TypeParameter::CheckedHandle(zone, decl_type_args_a1.TypeAt(1));
7530 auto& tav_a1_y = TypeArguments::Handle(TypeArguments::New(1));
7531 tav_a1_y.SetTypeAt(0, type_arg_a1_y);
7532 tav_a1_y = tav_a1_y.Canonicalize(thread);
7533 auto& type_list_a1_y = Type::CheckedHandle(
7534 zone, decl_type_list.InstantiateFrom(tav_a1_y, null_tav, kAllFree,
7535 Heap::kNew));
7536 type_list_a1_y ^= type_list_a1_y.Canonicalize(thread);
7537 auto& tav_list_a1_y = TypeArguments::Handle(TypeArguments::New(1));
7538 tav_list_a1_y.SetTypeAt(0, type_list_a1_y);
7539 tav_list_a1_y = tav_list_a1_y.Canonicalize(thread);
7540 auto& type_b_list_a1_y = Type::CheckedHandle(
7541 zone, decl_type_b.InstantiateFrom(tav_list_a1_y, null_tav, kAllFree,
7542 Heap::kNew));
7543 type_b_list_a1_y ^= type_b_list_a1_y.Canonicalize(thread);
7544
7545 const auto& inst_b_a1 =
7546 Type::Handle(zone, class_a1.GetInstantiationOf(zone, class_b));
7547 EXPECT(!inst_b_a1.IsNull());
7548 EXPECT_TYPES_EQUAL(type_b_list_a1_y, inst_b_a1);
7549 }
7550
7551 // Test that A2.GetInstantiationOf(B) returns B<List<A2::X>>.
7552 {
7553 const auto& decl_type_a2 = Type::Handle(zone, class_a2.DeclarationType());
7554 const auto& decl_type_args_a2 =
7555 TypeArguments::Handle(zone, decl_type_a2.arguments());
7556 const auto& type_arg_a2_x =
7557 TypeParameter::CheckedHandle(zone, decl_type_args_a2.TypeAt(0));
7558 auto& tav_a2_x = TypeArguments::Handle(TypeArguments::New(1));
7559 tav_a2_x.SetTypeAt(0, type_arg_a2_x);
7560 tav_a2_x = tav_a2_x.Canonicalize(thread);
7561 auto& type_list_a2_x = Type::CheckedHandle(
7562 zone, decl_type_list.InstantiateFrom(tav_a2_x, null_tav, kAllFree,
7563 Heap::kNew));
7564 type_list_a2_x ^= type_list_a2_x.Canonicalize(thread);
7565 auto& tav_list_a2_x = TypeArguments::Handle(TypeArguments::New(1));
7566 tav_list_a2_x.SetTypeAt(0, type_list_a2_x);
7567 tav_list_a2_x = tav_list_a2_x.Canonicalize(thread);
7568 auto& type_b_list_a2_x = Type::CheckedHandle(
7569 zone, decl_type_b.InstantiateFrom(tav_list_a2_x, null_tav, kAllFree,
7570 Heap::kNew));
7571 type_b_list_a2_x ^= type_b_list_a2_x.Canonicalize(thread);
7572
7573 const auto& inst_b_a2 =
7574 Type::Handle(zone, class_a2.GetInstantiationOf(zone, class_b));
7575 EXPECT(!inst_b_a2.IsNull());
7576 EXPECT_TYPES_EQUAL(type_b_list_a2_x, inst_b_a2);
7577 }
7578}
7579
7580#undef EXPECT_TYPES_EQUAL
7581
7582#define EXPECT_TYPES_SYNTACTICALLY_EQUIVALENT(expected, got) \
7583 ExpectTypesEquivalent(Expect(__FILE__, __LINE__), expected, got, \
7584 TypeEquality::kSyntactical);
7585
7586static TypePtr CreateFutureOrType(const AbstractType& param,
7587 Nullability nullability) {
7588 const auto& async_lib = Library::Handle(Library::AsyncLibrary());
7589 const auto& future_or_class =
7590 Class::Handle(async_lib.LookupClass(Symbols::FutureOr()));
7591 const auto& tav = TypeArguments::Handle(TypeArguments::New(1));
7592 tav.SetTypeAt(0, param);
7593 const auto& type =
7594 AbstractType::Handle(Type::New(future_or_class, tav, nullability));
7595 return Type::RawCast(
7597}
7598
7599static TypePtr CreateFutureType(const AbstractType& param,
7600 Nullability nullability) {
7601 ObjectStore* const object_store = IsolateGroup::Current()->object_store();
7602 const auto& future_class = Class::Handle(object_store->future_class());
7603 const auto& tav = TypeArguments::Handle(TypeArguments::New(1));
7604 tav.SetTypeAt(0, param);
7605 const auto& type = Type::Handle(Type::New(future_class, tav, nullability));
7606 return Type::RawCast(
7608}
7609
7610ISOLATE_UNIT_TEST_CASE(AbstractType_NormalizeFutureOrType) {
7611 // This should be kept up to date with any changes in
7612 // https://github.com/dart-lang/language/blob/master/resources/type-system/normalization.md
7613
7614 ObjectStore* const object_store = IsolateGroup::Current()->object_store();
7615
7616 auto normalized_future_or = [&](const AbstractType& param,
7617 Nullability nullability) -> AbstractTypePtr {
7618 const auto& type = Type::Handle(CreateFutureOrType(param, nullability));
7619 return type.NormalizeFutureOrType(Heap::kNew);
7620 };
7621
7622 // NORM(FutureOr<T>) =
7623 // let S be NORM(T)
7624 // if S is a top type then S
7625 {
7626 const auto& type = AbstractType::Handle(normalized_future_or(
7627 Object::dynamic_type(), Nullability::kNonNullable));
7628 EXPECT_TYPES_SYNTACTICALLY_EQUIVALENT(Object::dynamic_type(), type);
7629 }
7630
7631 {
7632 const auto& type = AbstractType::Handle(
7633 normalized_future_or(Object::void_type(), Nullability::kNonNullable));
7634 EXPECT_TYPES_SYNTACTICALLY_EQUIVALENT(Object::void_type(), type);
7635 }
7636
7637 {
7638 const auto& type_nullable_object =
7639 Type::Handle(object_store->nullable_object_type());
7640 const auto& type = AbstractType::Handle(
7641 normalized_future_or(type_nullable_object, Nullability::kNonNullable));
7642 EXPECT_TYPES_SYNTACTICALLY_EQUIVALENT(type_nullable_object, type);
7643 }
7644
7645 // if S is Object then S
7646
7647 {
7648 const auto& type_non_nullable_object =
7649 Type::Handle(object_store->non_nullable_object_type());
7650 const auto& type = AbstractType::Handle(normalized_future_or(
7651 type_non_nullable_object, Nullability::kNonNullable));
7652 EXPECT_TYPES_SYNTACTICALLY_EQUIVALENT(type_non_nullable_object, type);
7653 }
7654
7655 // if S is Never then Future<Never>
7656
7657 {
7658 const auto& type_never = Type::Handle(object_store->never_type());
7659 const auto& expected =
7661 const auto& got = AbstractType::Handle(
7662 normalized_future_or(type_never, Nullability::kNonNullable));
7664 }
7665
7666 // if S is Null then Future<Null>?
7667
7668 {
7669 const auto& type_null = Type::Handle(object_store->null_type());
7670 const auto& expected =
7672 const auto& got = AbstractType::Handle(
7673 normalized_future_or(type_null, Nullability::kNonNullable));
7675 }
7676
7677 // else FutureOr<S>
7678
7679 // NORM(T?) =
7680 // let S be NORM(T)
7681 // ...
7682 // if S is FutureOr<R> and R is nullable then S
7683
7685 const auto& type_nullable_int =
7686 Type::Handle(object_store->nullable_int_type());
7687 const auto& expected = Type::Handle(
7688 CreateFutureOrType(type_nullable_int, Nullability::kNonNullable));
7689 const auto& got = AbstractType::Handle(
7690 normalized_future_or(type_nullable_int, Nullability::kNullable));
7692 }
7693}
7694
7695TEST_CASE(AbstractType_InstantiatedFutureOrIsNormalized) {
7696 const char* kScript = R"(
7697import 'dart:async';
7698
7699FutureOr<T>? foo<T>() { return null; }
7700FutureOr<T?> bar<T>() { return null; }
7701)";
7702
7703 Dart_Handle api_lib = TestCase::LoadTestScript(kScript, nullptr);
7704 EXPECT_VALID(api_lib);
7705 TransitionNativeToVM transition(thread);
7706 Zone* const zone = thread->zone();
7707 ObjectStore* const object_store = IsolateGroup::Current()->object_store();
7708
7709 const auto& null_tav = Object::null_type_arguments();
7710 auto instantiate_future_or =
7711 [&](const AbstractType& generic,
7712 const AbstractType& param) -> AbstractTypePtr {
7713 const auto& tav = TypeArguments::Handle(TypeArguments::New(1));
7714 tav.SetTypeAt(0, param);
7715 return generic.InstantiateFrom(null_tav, tav, kCurrentAndEnclosingFree,
7716 Heap::kNew);
7717 };
7718
7719 const auto& root_lib =
7720 Library::CheckedHandle(zone, Api::UnwrapHandle(api_lib));
7721 EXPECT(!root_lib.IsNull());
7722 const auto& foo = Function::Handle(zone, GetFunction(root_lib, "foo"));
7723 const auto& bar = Function::Handle(zone, GetFunction(root_lib, "bar"));
7724 const auto& foo_sig = FunctionType::Handle(zone, foo.signature());
7725 const auto& bar_sig = FunctionType::Handle(zone, bar.signature());
7726
7727 const auto& nullable_future_or_T =
7728 AbstractType::Handle(zone, foo_sig.result_type());
7729 const auto& future_or_nullable_T =
7730 AbstractType::Handle(zone, bar_sig.result_type());
7731
7732 const auto& type_nullable_object =
7733 Type::Handle(object_store->nullable_object_type());
7734 const auto& type_non_nullable_object =
7735 Type::Handle(object_store->non_nullable_object_type());
7736
7737 // Testing same cases as AbstractType_NormalizeFutureOrType.
7738
7739 // FutureOr<T>?[top type] = top type
7740
7741 {
7742 const auto& got = AbstractType::Handle(
7743 instantiate_future_or(nullable_future_or_T, Object::dynamic_type()));
7744 EXPECT_TYPES_SYNTACTICALLY_EQUIVALENT(Object::dynamic_type(), got);
7745 }
7746
7747 {
7748 const auto& got = AbstractType::Handle(
7749 instantiate_future_or(nullable_future_or_T, Object::void_type()));
7750 EXPECT_TYPES_SYNTACTICALLY_EQUIVALENT(Object::void_type(), got);
7751 }
7752
7753 {
7754 const auto& got = AbstractType::Handle(
7755 instantiate_future_or(nullable_future_or_T, type_nullable_object));
7756 EXPECT_TYPES_SYNTACTICALLY_EQUIVALENT(type_nullable_object, got);
7757 }
7758
7759 // FutureOr<T?>[top type] = top type
7760
7761 {
7762 const auto& got = AbstractType::Handle(
7763 instantiate_future_or(future_or_nullable_T, Object::dynamic_type()));
7764 EXPECT_TYPES_SYNTACTICALLY_EQUIVALENT(Object::dynamic_type(), got);
7765 }
7766
7767 {
7768 const auto& got = AbstractType::Handle(
7769 instantiate_future_or(future_or_nullable_T, Object::void_type()));
7770 EXPECT_TYPES_SYNTACTICALLY_EQUIVALENT(Object::void_type(), got);
7771 }
7772
7773 {
7774 const auto& got = AbstractType::Handle(
7775 instantiate_future_or(future_or_nullable_T, type_nullable_object));
7776 EXPECT_TYPES_SYNTACTICALLY_EQUIVALENT(type_nullable_object, got);
7777 }
7778
7779 // FutureOr<T?>[Object] = Object?
7780
7781 {
7782 const auto& got = AbstractType::Handle(
7783 instantiate_future_or(future_or_nullable_T, type_non_nullable_object));
7784 EXPECT_TYPES_SYNTACTICALLY_EQUIVALENT(type_nullable_object, got);
7785 }
7786
7787 // FutureOr<T>?[Object] = Object?
7788
7789 {
7790 const auto& got = AbstractType::Handle(
7791 instantiate_future_or(nullable_future_or_T, type_non_nullable_object));
7792 EXPECT_TYPES_SYNTACTICALLY_EQUIVALENT(type_nullable_object, got);
7793 }
7794
7795 const auto& type_never = Type::Handle(object_store->never_type());
7796 const auto& type_null = Type::Handle(object_store->null_type());
7797
7798 // FutureOr<T?>[Never] = Future<Null>?
7799
7800 {
7801 const auto& expected =
7803 const auto& got = AbstractType::Handle(
7804 instantiate_future_or(future_or_nullable_T, type_never));
7806 }
7807
7808 // FutureOr<T>?[Never] = Future<Never>?
7809
7810 {
7811 const auto& expected =
7813 const auto& got = AbstractType::Handle(
7814 instantiate_future_or(nullable_future_or_T, type_never));
7816 }
7817
7818 // FutureOr<T?>[Null] = Future<Null>?
7819
7820 {
7821 const auto& expected =
7823 const auto& got = AbstractType::Handle(
7824 instantiate_future_or(future_or_nullable_T, type_null));
7826 }
7827
7828 // FutureOr<T>?[Null] = Future<Null>?
7829
7830 {
7831 const auto& expected =
7833 const auto& got = AbstractType::Handle(
7834 instantiate_future_or(nullable_future_or_T, type_null));
7836 }
7837
7838 const auto& type_nullable_int =
7839 Type::Handle(object_store->nullable_int_type());
7840 const auto& type_non_nullable_int =
7841 Type::Handle(object_store->non_nullable_int_type());
7842
7843 // FutureOr<T?>[int] = FutureOr<int?>
7844
7845 {
7846 const auto& expected = Type::Handle(
7847 CreateFutureOrType(type_nullable_int, Nullability::kNonNullable));
7848 const auto& got = AbstractType::Handle(
7849 instantiate_future_or(future_or_nullable_T, type_non_nullable_int));
7851 }
7852
7853 // FutureOr<T?>[int?] = FutureOr<int?>
7854
7855 {
7856 const auto& expected = Type::Handle(
7857 CreateFutureOrType(type_nullable_int, Nullability::kNonNullable));
7858 const auto& got = AbstractType::Handle(
7859 instantiate_future_or(future_or_nullable_T, type_nullable_int));
7861 }
7862
7863 // FutureOr<T>?[int?] = FutureOr<int?>
7864
7865 {
7866 const auto& expected = Type::Handle(
7867 CreateFutureOrType(type_nullable_int, Nullability::kNonNullable));
7868 const auto& got = AbstractType::Handle(
7869 instantiate_future_or(nullable_future_or_T, type_nullable_int));
7871 }
7872
7873 // FutureOr<T>?[int] = FutureOr<int>?
7874
7876 const auto& expected = Type::Handle(
7877 CreateFutureOrType(type_non_nullable_int, Nullability::kNullable));
7878 const auto& got = AbstractType::Handle(
7879 instantiate_future_or(nullable_future_or_T, type_non_nullable_int));
7881 }
7882}
7883
7884#define __ assembler->
7885
7886static void GenerateInvokeInstantiateTAVStub(compiler::Assembler* assembler) {
7887 __ EnterDartFrame(0);
7888
7889 // Load the arguments into the right stub calling convention registers.
7890 const intptr_t uninstantiated_offset =
7892 const intptr_t inst_type_args_offset =
7894 const intptr_t fun_type_args_offset =
7896
7898 uninstantiated_offset);
7900 inst_type_args_offset);
7902 fun_type_args_offset);
7903
7904 __ Call(StubCode::InstantiateTypeArguments());
7905
7906 // Set the return from the stub.
7909 __ LeaveDartFrame();
7910 __ Ret();
7911}
7912
7913#undef __
7914
7915static CodePtr CreateInvokeInstantiateTypeArgumentsStub(Thread* thread) {
7916 Zone* const zone = thread->zone();
7917 const auto& klass = Class::Handle(
7918 zone, thread->isolate_group()->class_table()->At(kInstanceCid));
7919 const auto& symbol = String::Handle(
7920 zone, Symbols::New(thread, OS::SCreate(zone, "InstantiateTAVTest")));
7921 const auto& signature = FunctionType::Handle(zone, FunctionType::New());
7922 const auto& function = Function::Handle(
7923 zone, Function::New(signature, symbol, UntaggedFunction::kRegularFunction,
7924 false, false, false, false, false, klass,
7925 TokenPosition::kNoSource));
7926
7927 compiler::ObjectPoolBuilder pool_builder;
7928 SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
7929 compiler::Assembler assembler(&pool_builder);
7931 const Code& invoke_instantiate_tav = Code::Handle(
7932 Code::FinalizeCodeAndNotify("InstantiateTAV", nullptr, &assembler,
7934 /*optimized=*/false));
7935
7936 const auto& pool =
7938 invoke_instantiate_tav.set_object_pool(pool.ptr());
7939 invoke_instantiate_tav.set_owner(function);
7940 invoke_instantiate_tav.set_exception_handlers(
7942#if defined(TARGET_ARCH_IA32)
7943 EXPECT_EQ(0, pool.Length());
7944#else
7945 EXPECT_EQ(1, pool.Length()); // The InstantiateTypeArguments stub.
7946#endif
7947 return invoke_instantiate_tav.ptr();
7948}
7949
7950#if !defined(PRODUCT)
7951// Defined before TypeArguments::InstantiateAndCanonicalizeFrom in object.cc.
7953#endif
7954
7955static void TypeArgumentsHashCacheTest(Thread* thread, intptr_t num_classes) {
7956 TextBuffer buffer(MB);
7957 buffer.AddString("class D<T> {}\n");
7958 for (intptr_t i = 0; i < num_classes; i++) {
7959 buffer.Printf("class C%" Pd " { String toString() => 'C%" Pd "'; }\n", i,
7960 i);
7961 }
7962 buffer.AddString("main() {\n");
7963 for (intptr_t i = 0; i < num_classes; i++) {
7964 buffer.Printf(" C%" Pd "().toString();\n", i);
7965 }
7966 buffer.AddString("}\n");
7967
7968 Dart_Handle api_lib = TestCase::LoadTestScript(buffer.buffer(), nullptr);
7969 EXPECT_VALID(api_lib);
7970 Dart_Handle result = Dart_Invoke(api_lib, NewString("main"), 0, nullptr);
7972
7973 // D + C0...CN, where N = kNumClasses - 1
7974 EXPECT(IsolateGroup::Current()->class_table()->NumCids() > num_classes);
7975
7976 TransitionNativeToVM transition(thread);
7977 Zone* const zone = thread->zone();
7978
7979 const auto& root_lib =
7980 Library::CheckedHandle(zone, Api::UnwrapHandle(api_lib));
7981 EXPECT(!root_lib.IsNull());
7982
7983 const auto& class_d = Class::Handle(zone, GetClass(root_lib, "D"));
7984 ASSERT(!class_d.IsNull());
7985 const auto& decl_type_d = Type::Handle(zone, class_d.DeclarationType());
7986 const auto& decl_type_d_type_args =
7987 TypeArguments::Handle(zone, decl_type_d.arguments());
7988
7989 EXPECT(!decl_type_d_type_args.HasInstantiations());
7990
7991 auto& class_c = Class::Handle(zone);
7992 auto& decl_type_c = Type::Handle(zone);
7993 auto& instantiator_type_args = TypeArguments::Handle(zone);
7994 const auto& function_type_args = Object::null_type_arguments();
7995 auto& result_type_args = TypeArguments::Handle(zone);
7996 auto& result_type = AbstractType::Handle(zone);
7997 // Cache the first computed set of instantiator type arguments to check that
7998 // no entries from the cache have been lost when the cache grows.
7999 auto& first_instantiator_type_args = TypeArguments::Handle(zone);
8000 // Used for the cache hit in stub check.
8001 const auto& invoke_instantiate_tav =
8003 const auto& invoke_instantiate_tav_arguments =
8004 Array::Handle(zone, Array::New(3));
8005 const auto& invoke_instantiate_tav_args_descriptor =
8007 for (intptr_t i = 0; i < num_classes; ++i) {
8008 const bool updated_cache_is_linear =
8010 auto const name = OS::SCreate(zone, "C%" Pd "", i);
8011 class_c = GetClass(root_lib, name);
8012 ASSERT(!class_c.IsNull());
8013 decl_type_c = class_c.DeclarationType();
8014 instantiator_type_args = TypeArguments::New(1);
8015 instantiator_type_args.SetTypeAt(0, decl_type_c);
8016 instantiator_type_args = instantiator_type_args.Canonicalize(thread);
8017
8018#if !defined(PRODUCT)
8019 // The first call to InstantiateAndCanonicalizeFrom shouldn't have a cache
8020 // hit since the instantiator type arguments should be unique for each
8021 // iteration, and after that we do a check that the InstantiateTypeArguments
8022 // stub finds the entry (unless the cache is hash-based on IA32).
8024#endif
8025
8026 // Check that the key does not currently exist in the cache.
8027 intptr_t old_capacity;
8028 {
8029 SafepointMutexLocker ml(
8030 thread->isolate_group()->type_arguments_canonicalization_mutex());
8031 TypeArguments::Cache cache(zone, decl_type_d_type_args);
8032 EXPECT_EQ(i, cache.NumOccupied());
8033 auto loc =
8034 cache.FindKeyOrUnused(instantiator_type_args, function_type_args);
8035 EXPECT(!loc.present);
8036 old_capacity = cache.NumEntries();
8037 }
8038
8039 decl_type_d_type_args.InstantiateAndCanonicalizeFrom(instantiator_type_args,
8040 function_type_args);
8041
8042 // Check that the key now does exist in the cache.
8043 TypeArguments::Cache::KeyLocation loc;
8044 bool storage_changed;
8045 {
8046 SafepointMutexLocker ml(
8047 thread->isolate_group()->type_arguments_canonicalization_mutex());
8048 TypeArguments::Cache cache(zone, decl_type_d_type_args);
8049 EXPECT_EQ(i + 1, cache.NumOccupied());
8050 // Double-check that we got the expected type of cache.
8051 EXPECT(updated_cache_is_linear ? cache.IsLinear() : cache.IsHash());
8052 loc = cache.FindKeyOrUnused(instantiator_type_args, function_type_args);
8053 EXPECT(loc.present);
8054 storage_changed = cache.NumEntries() != old_capacity;
8055 }
8056
8057#if defined(TARGET_ARCH_IA32)
8058 const bool stub_checks_hash_caches = false;
8059#else
8060 const bool stub_checks_hash_caches = true;
8061#endif
8062 // Now check that we get the expected result from calling the stub if it
8063 // checks the cache (e.g., in all cases but hash-based caches on IA32).
8064 if (updated_cache_is_linear || stub_checks_hash_caches) {
8065 invoke_instantiate_tav_arguments.SetAt(0, decl_type_d_type_args);
8066 invoke_instantiate_tav_arguments.SetAt(1, instantiator_type_args);
8067 invoke_instantiate_tav_arguments.SetAt(2, function_type_args);
8068 result_type_args ^= DartEntry::InvokeCode(
8069 invoke_instantiate_tav, invoke_instantiate_tav_args_descriptor,
8070 invoke_instantiate_tav_arguments, thread);
8071 EXPECT_EQ(1, result_type_args.Length());
8072 result_type = result_type_args.TypeAt(0);
8073 EXPECT_TYPES_SYNTACTICALLY_EQUIVALENT(decl_type_c, result_type);
8074 }
8075
8076#if !defined(PRODUCT)
8077 // Setting to false prior to re-calling InstantiateAndCanonicalizeFrom with
8078 // the same keys, as now we want a runtime check of an existing cache entry.
8080#endif
8081
8082 result_type_args = decl_type_d_type_args.InstantiateAndCanonicalizeFrom(
8083 instantiator_type_args, function_type_args);
8084 result_type = result_type_args.TypeAt(0);
8085 EXPECT_TYPES_SYNTACTICALLY_EQUIVALENT(decl_type_c, result_type);
8086
8087 // Check that no new entries were added to the cache.
8088 {
8089 SafepointMutexLocker ml(
8090 thread->isolate_group()->type_arguments_canonicalization_mutex());
8091 TypeArguments::Cache cache(zone, decl_type_d_type_args);
8092 EXPECT_EQ(i + 1, cache.NumOccupied());
8093 auto const loc2 =
8094 cache.FindKeyOrUnused(instantiator_type_args, function_type_args);
8095 EXPECT(loc2.present);
8096 EXPECT_EQ(loc.entry, loc2.entry);
8097 }
8098
8099 if (i == 0) {
8100 first_instantiator_type_args = instantiator_type_args.ptr();
8101 } else if (storage_changed) {
8102 // Check that the first instantiator TAV still exists in the new cache.
8103 SafepointMutexLocker ml(
8104 thread->isolate_group()->type_arguments_canonicalization_mutex());
8105 TypeArguments::Cache cache(zone, decl_type_d_type_args);
8106 EXPECT_EQ(i + 1, cache.NumOccupied());
8107 // Double-check that we got the expected type of cache.
8109 : cache.IsHash());
8110 auto const loc =
8111 cache.FindKeyOrUnused(instantiator_type_args, function_type_args);
8112 EXPECT(loc.present);
8113 }
8114 }
8115}
8116
8117// A smaller version of the following test case, just to ensure some coverage
8118// on slower builds.
8119TEST_CASE(TypeArguments_Cache_SomeInstantiations) {
8122}
8123
8124// Too slow in debug mode. Also avoid the sanitizers and simulators for similar
8125// reasons. Any core issues will likely be found by SomeInstantiations.
8126#if !defined(DEBUG) && !defined(USING_MEMORY_SANITIZER) && \
8127 !defined(USING_THREAD_SANITIZER) && !defined(USING_LEAK_SANITIZER) && \
8128 !defined(USING_UNDEFINED_BEHAVIOR_SANITIZER) && !defined(USING_SIMULATOR)
8129TEST_CASE(TypeArguments_Cache_ManyInstantiations) {
8130 const intptr_t kNumClasses = 100000;
8131 static_assert(kNumClasses > TypeArguments::Cache::kMaxLinearCacheEntries,
8132 "too few classes to trigger change to a hash-based cache");
8133 TypeArgumentsHashCacheTest(thread, kNumClasses);
8134}
8135#endif
8136
8137#undef EXPECT_TYPES_SYNTACTICALLY_EQUIVALENT
8138
8139static void SubtypeTestCacheCheckContents(Zone* zone,
8140 const SubtypeTestCache& cache) {
8141 const intptr_t used_inputs = cache.num_inputs();
8142 if (used_inputs < 1 || used_inputs > SubtypeTestCache::kMaxInputs) {
8143 FAIL("Invalid number of used inputs: %" Pd "", used_inputs);
8144 return;
8145 }
8146 const auto& array = Array::Handle(zone, cache.cache());
8147 for (intptr_t i = 0; i < cache.NumEntries(); i++) {
8148 if (!cache.IsOccupied(i)) continue;
8149 const intptr_t entry_start = i * SubtypeTestCache::kTestEntryLength;
8150 {
8151 const intptr_t cid =
8152 array.At(entry_start + SubtypeTestCache::kTestResult)
8154 EXPECT(cid == kNullCid || cid == kBoolCid);
8155 }
8156
8157 // Used to make sure all the cases are in the correct order below.
8158 int check_ordering = used_inputs;
8159 // Input: the value of SubtypeTestCache::Entries for this input
8160 // ExpectedCids is an expression where [cid] is bound to the contents cid.
8161#define USED_INPUT_CASE(Input, ExpectedCids) \
8162 case (Input) + 1: { \
8163 RELEASE_ASSERT((Input) + 1 == check_ordering); \
8164 const intptr_t cid = \
8165 array.At(entry_start + (Input))->GetClassIdMayBeSmi(); \
8166 if (!(ExpectedCids)) { \
8167 FAIL("expected: " #ExpectedCids ", got: cid %" Pd "", cid); \
8168 } \
8169 --check_ordering; \
8170 }
8171
8172 switch (used_inputs) {
8177 cid == kNullCid || cid == kTypeArgumentsCid);
8180 cid == kNullCid || cid == kTypeArgumentsCid);
8183 cid == kNullCid || cid == kTypeArgumentsCid);
8186 cid == kNullCid || cid == kTypeArgumentsCid);
8189 cid == kNullCid || cid == kTypeArgumentsCid);
8192 cid == kSmiCid || cid == kFunctionTypeCid);
8193 break;
8194 default:
8195 UNREACHABLE();
8196 }
8197
8198#undef USED_INPUT_CASE
8199 RELEASE_ASSERT(0 == check_ordering);
8200
8201 // Check that unused inputs have never been set.
8202 for (intptr_t i = used_inputs; i < SubtypeTestCache::kMaxInputs; i++) {
8203 // Since we sometimes use Array::NewUninitialized() for allocations of
8204 // STCs and never set unused inputs, the only thing we know is that the
8205 // entry is GC-safe. Since we don't expect valid values for unused inputs,
8206 // we just check if it's either a Smi or null.
8207 const intptr_t cid = array.At(entry_start + i)->GetClassIdMayBeSmi();
8208 EXPECT(cid == kSmiCid || cid == kNullCid);
8209 }
8210 }
8211}
8212
8213static void SubtypeTestCacheEntryTest(
8214 Thread* thread,
8215 const SubtypeTestCache& cache,
8216 const Object& instance_class_id_or_signature,
8217 const AbstractType& destination_type,
8218 const TypeArguments& instance_type_arguments,
8219 const TypeArguments& instantiator_type_arguments,
8220 const TypeArguments& function_type_arguments,
8221 const TypeArguments& parent_function_type_arguments,
8222 const TypeArguments& delayed_type_arguments,
8223 const Bool& expected_result,
8224 Bool* got_result) {
8225 const auto& tav_null = TypeArguments::null_type_arguments();
8226 const intptr_t num_inputs = cache.num_inputs();
8227 const bool was_hash = cache.IsHash();
8228 const intptr_t old_count = cache.NumberOfChecks();
8229 intptr_t expected_index, got_index;
8230
8231 EXPECT(!cache.HasCheck(
8232 instance_class_id_or_signature, destination_type, instance_type_arguments,
8233 instantiator_type_arguments, function_type_arguments,
8234 parent_function_type_arguments, delayed_type_arguments, /*index=*/nullptr,
8235 /*result=*/nullptr));
8236 {
8237 SafepointMutexLocker ml(
8238 thread->isolate_group()->subtype_test_cache_mutex());
8239 expected_index =
8240 cache.AddCheck(instance_class_id_or_signature, destination_type,
8241 instance_type_arguments, instantiator_type_arguments,
8242 function_type_arguments, parent_function_type_arguments,
8243 delayed_type_arguments, expected_result);
8244 EXPECT(expected_index >= 0);
8245 }
8246 EXPECT_EQ(old_count + 1, cache.NumberOfChecks());
8247 EXPECT(cache.HasCheck(instance_class_id_or_signature, destination_type,
8248 instance_type_arguments, instantiator_type_arguments,
8249 function_type_arguments, parent_function_type_arguments,
8250 delayed_type_arguments, &got_index, got_result));
8251 EXPECT_EQ(expected_index, got_index);
8252 EXPECT(got_result->ptr() == expected_result.ptr());
8253 if (num_inputs < (SubtypeTestCache::kInstanceTypeArguments + 1)) {
8254 // Match replacing unused instance type arguments with null.
8255 EXPECT(cache.HasCheck(instance_class_id_or_signature, destination_type,
8256 tav_null, instantiator_type_arguments,
8257 function_type_arguments,
8258 parent_function_type_arguments,
8259 delayed_type_arguments, &got_index, got_result));
8260 EXPECT_EQ(expected_index, got_index);
8261 EXPECT(got_result->ptr() == expected_result.ptr());
8262 } else {
8263 // No match replacing used instance type arguments with null.
8264 EXPECT(!cache.HasCheck(
8265 instance_class_id_or_signature, destination_type, tav_null,
8266 instantiator_type_arguments, function_type_arguments,
8267 parent_function_type_arguments, delayed_type_arguments,
8268 /*index=*/nullptr, /*result=*/nullptr));
8269 }
8270 if (num_inputs < (SubtypeTestCache::kInstantiatorTypeArguments + 1)) {
8271 // Match replacing unused instantiator type arguments with null.
8272 EXPECT(cache.HasCheck(instance_class_id_or_signature, destination_type,
8273 instance_type_arguments, tav_null,
8274 function_type_arguments,
8275 parent_function_type_arguments,
8276 delayed_type_arguments, &got_index, got_result));
8277 EXPECT_EQ(expected_index, got_index);
8278 EXPECT(got_result->ptr() == expected_result.ptr());
8279 } else {
8280 // No match replacing used instantiator type arguments with null.
8281 EXPECT(!cache.HasCheck(
8282 instance_class_id_or_signature, destination_type,
8283 instance_type_arguments, tav_null, function_type_arguments,
8284 parent_function_type_arguments, delayed_type_arguments,
8285 /*index=*/nullptr, /*result=*/nullptr));
8286 }
8287 if (num_inputs < (SubtypeTestCache::kFunctionTypeArguments + 1)) {
8288 // Match replacing unused function type arguments with null.
8289 EXPECT(cache.HasCheck(instance_class_id_or_signature, destination_type,
8290 instance_type_arguments, instantiator_type_arguments,
8291 tav_null, parent_function_type_arguments,
8292 delayed_type_arguments, &got_index, got_result));
8293 EXPECT_EQ(expected_index, got_index);
8294 EXPECT(got_result->ptr() == expected_result.ptr());
8295 } else {
8296 // No match replacing used function type arguments with null.
8297 EXPECT(!cache.HasCheck(instance_class_id_or_signature, destination_type,
8298 instance_type_arguments, instantiator_type_arguments,
8299 tav_null, parent_function_type_arguments,
8300 delayed_type_arguments,
8301 /*index=*/nullptr, /*result=*/nullptr));
8302 }
8303 if (num_inputs <
8305 // Match replacing unused parent function type arguments with null.
8306 EXPECT(cache.HasCheck(instance_class_id_or_signature, destination_type,
8307 instance_type_arguments, instantiator_type_arguments,
8308 function_type_arguments, tav_null,
8309 delayed_type_arguments, &got_index, got_result));
8310 EXPECT_EQ(expected_index, got_index);
8311 EXPECT(got_result->ptr() == expected_result.ptr());
8312 } else {
8313 // No match replacing used parent function type arguments with null.
8314 EXPECT(!cache.HasCheck(instance_class_id_or_signature, destination_type,
8315 instance_type_arguments, instantiator_type_arguments,
8316 function_type_arguments, tav_null,
8317 delayed_type_arguments, /*index=*/nullptr,
8318 /*result=*/nullptr));
8319 }
8320 if (num_inputs <
8322 // Match replacing unused delayed type arguments with null.
8323 EXPECT(cache.HasCheck(instance_class_id_or_signature, destination_type,
8324 instance_type_arguments, instantiator_type_arguments,
8325 function_type_arguments,
8326 parent_function_type_arguments, tav_null, &got_index,
8327 got_result));
8328 EXPECT_EQ(expected_index, got_index);
8329 EXPECT(got_result->ptr() == expected_result.ptr());
8330 } else {
8331 // No match replacing used delayed type arguments with null.
8332 EXPECT(!cache.HasCheck(instance_class_id_or_signature, destination_type,
8333 instance_type_arguments, instantiator_type_arguments,
8334 function_type_arguments,
8335 parent_function_type_arguments, tav_null,
8336 /*index=*/nullptr, /*result=*/nullptr));
8337 }
8338 // Make sure we're not accidentally using the same type as the input below.
8339 RELEASE_ASSERT(destination_type.ptr() != Type::VoidType());
8340 if (num_inputs < (SubtypeTestCache::kDestinationType + 1)) {
8341 // Match replacing unused destination type argument with the null type.
8342 EXPECT(cache.HasCheck(instance_class_id_or_signature, Object::void_type(),
8343 instance_type_arguments, instantiator_type_arguments,
8344 function_type_arguments,
8345 parent_function_type_arguments,
8346 delayed_type_arguments, &got_index, got_result));
8347 EXPECT_EQ(expected_index, got_index);
8348 EXPECT(got_result->ptr() == expected_result.ptr());
8349 } else {
8350 // No match replacing used destination type argument with the null type.
8351 EXPECT(!cache.HasCheck(instance_class_id_or_signature, Object::void_type(),
8352 instance_type_arguments, instantiator_type_arguments,
8353 function_type_arguments,
8354 parent_function_type_arguments,
8355 delayed_type_arguments,
8356 /*index=*/nullptr, /*result=*/nullptr));
8357 }
8358 // Once hash-based, should stay a hash-based cache.
8359 EXPECT(!was_hash || cache.IsHash());
8360}
8361
8362static void SubtypeTestCacheTest(Thread* thread,
8363 intptr_t num_classes,
8364 bool expect_hash) {
8365 TextBuffer buffer(MB);
8366 buffer.AddString("class D {}\n");
8367 buffer.AddString("D createInstanceD() => D();");
8368 buffer.AddString("D Function() createClosureD() => () => D();\n");
8369 for (intptr_t i = 0; i < num_classes; i++) {
8370 buffer.Printf(R"(class C%)" Pd R"( extends D {}
8371)"
8372 R"(C%)" Pd R"( createInstanceC%)" Pd R"(() => C%)" Pd
8373 R"(();
8374)"
8375 R"(C%)" Pd R"( Function() createClosureC%)" Pd
8376 R"(() => () => C%)" Pd
8377 R"(();
8378)",
8379 i, i, i, i, i, i, i);
8380 }
8381
8382 Dart_Handle api_lib = TestCase::LoadTestScript(buffer.buffer(), nullptr);
8383 EXPECT_VALID(api_lib);
8384
8385 // D + C0...CN, where N = kNumClasses - 1
8386 EXPECT(IsolateGroup::Current()->class_table()->NumCids() > num_classes);
8387
8388 TransitionNativeToVM transition(thread);
8389 Zone* const zone = thread->zone();
8390
8391 const auto& root_lib =
8392 Library::CheckedHandle(zone, Api::UnwrapHandle(api_lib));
8393 EXPECT(!root_lib.IsNull());
8394
8395 const auto& class_d = Class::Handle(zone, GetClass(root_lib, "D"));
8396 ASSERT(!class_d.IsNull());
8397 {
8398 SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
8400 }
8401 const auto& instance_d =
8402 Instance::CheckedHandle(zone, Invoke(root_lib, "createInstanceD"));
8403 auto& type_instance_d_int =
8404 Type::CheckedHandle(zone, instance_d.GetType(Heap::kNew));
8405 const auto& closure_d =
8406 Instance::CheckedHandle(zone, Invoke(root_lib, "createClosureD"));
8407 ASSERT(!closure_d.IsNull());
8408 auto& type_closure_d_int =
8409 FunctionType::CheckedHandle(zone, closure_d.GetType(Heap::kNew));
8410
8411 // Test all the possible input values.
8412 const SubtypeTestCache* stcs[SubtypeTestCache::kMaxInputs];
8413 for (intptr_t i = 0; i < SubtypeTestCache::kMaxInputs; i++) {
8415 }
8416
8417 auto& class_c = Class::Handle(zone);
8418 auto& instance_c = Instance::Handle(zone);
8419 auto& closure_c = Closure::Handle(zone);
8420 auto& instance_class_id_or_signature = Object::Handle(zone);
8421 // Set up unique tavs for each of the TAV inputs.
8422 auto& instance_type_arguments =
8424 instance_type_arguments.SetTypeAt(0, Type::Handle(zone, Type::SmiType()));
8425 instance_type_arguments = instance_type_arguments.Canonicalize(thread);
8426 auto& instantiator_type_arguments =
8428 instantiator_type_arguments.SetTypeAt(0, Type::Handle(zone, Type::IntType()));
8429 instantiator_type_arguments =
8430 instantiator_type_arguments.Canonicalize(thread);
8431 auto& function_type_arguments =
8433 function_type_arguments.SetTypeAt(0, Type::Handle(zone, Type::Double()));
8434 function_type_arguments = function_type_arguments.Canonicalize(thread);
8435 auto& parent_function_type_arguments =
8437 parent_function_type_arguments.SetTypeAt(
8438 0, Type::Handle(zone, Type::StringType()));
8439 parent_function_type_arguments =
8440 parent_function_type_arguments.Canonicalize(thread);
8441 auto& delayed_type_arguments =
8443 delayed_type_arguments.SetTypeAt(0, Type::Handle(zone, Type::BoolType()));
8444 delayed_type_arguments = delayed_type_arguments.Canonicalize(thread);
8445 auto& got_result = Bool::Handle(zone);
8446 for (intptr_t i = 0; i < num_classes; ++i) {
8447 // Just so we're testing both true and false values, as we're not actually
8448 // using the results to determine subtype/assignability.
8449 const auto& expected_result = (i % 2 == 0) ? Bool::True() : Bool::False();
8450
8451 auto const class_name = OS::SCreate(zone, "C%" Pd "", i);
8452 class_c = GetClass(root_lib, class_name);
8453 ASSERT(!class_c.IsNull());
8454 {
8455 SafepointWriteRwLocker ml(thread,
8456 thread->isolate_group()->program_lock());
8458 }
8459 auto const instance_name = OS::SCreate(zone, "createInstanceC%" Pd "", i);
8460 instance_c ^= Invoke(root_lib, instance_name);
8461 EXPECT(!instance_c.IsClosure());
8462 instance_class_id_or_signature = Smi::New(instance_c.GetClassId());
8463
8464 for (intptr_t i = 0; i < 5; i++) {
8466 thread, *stcs[i], instance_class_id_or_signature, type_instance_d_int,
8467 instance_type_arguments, instantiator_type_arguments,
8468 function_type_arguments, parent_function_type_arguments,
8469 delayed_type_arguments, expected_result, &got_result);
8470 }
8471
8472 auto const function_name = OS::SCreate(zone, "createClosureC%" Pd "", i);
8473 closure_c ^= Invoke(root_lib, function_name);
8474
8475 instance_class_id_or_signature = closure_c.function();
8476 instance_class_id_or_signature =
8477 Function::Cast(instance_class_id_or_signature).signature();
8478
8479 for (intptr_t i = 5; i < SubtypeTestCache::kMaxInputs; i++) {
8481 thread, *stcs[i], instance_class_id_or_signature, type_closure_d_int,
8482 instance_type_arguments, instantiator_type_arguments,
8483 function_type_arguments, parent_function_type_arguments,
8484 delayed_type_arguments, expected_result, &got_result);
8486 }
8487 for (intptr_t i = 0; i < SubtypeTestCache::kMaxInputs; i++) {
8488 SubtypeTestCacheCheckContents(zone, *stcs[i]);
8489 EXPECT_EQ(expect_hash, stcs[i]->IsHash());
8490 }
8491}
8492
8493TEST_CASE(STC_LinearLookup) {
8495 /*expect_hash=*/false);
8496}
8497
8498TEST_CASE(STC_HashLookup) {
8500 /*expect_hash=*/true);
8501}
8502
8503} // namespace dart
AutoreleasePool pool
static BlurTest tests[]
Definition: BlurTest.cpp:84
static void check_data(skiatest::Reporter *reporter, SkCachedData *data, int refcnt, CachedState cacheState, LockedState lockedState)
static void done(const char *config, const char *src, const char *srcOptions, const char *name)
Definition: DM.cpp:263
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition: DM.cpp:213
int count
Definition: FontMgrTest.cpp:50
static const size_t kBufferSize
Definition: SkString.cpp:27
SI F table(const skcms_Curve *curve, F v)
#define EXPECT(type, expectedAlignment, expectedSize)
#define UNREACHABLE()
Definition: assert.h:248
#define RELEASE_ASSERT(cond)
Definition: assert.h:327
GLenum type
static Dart_Handle NewHandle(Thread *thread, ObjectPtr raw)
static ObjectPtr UnwrapHandle(Dart_Handle object)
static ArrayPtr NewBoxed(intptr_t type_args_len, intptr_t num_arguments, const Array &optional_arguments_names, Heap::Space space=Heap::kOld)
Definition: dart_entry.h:83
static intptr_t InstanceSize()
Definition: object.h:10936
static constexpr intptr_t kMaxElements
Definition: object.h:10924
static ArrayPtr New(intptr_t len, Heap::Space space=Heap::kNew)
Definition: object.h:10959
virtual bool CanonicalizeEquals(const Instance &other) const
Definition: object.cc:24702
void MakeImmutable() const
Definition: object.cc:24837
static constexpr bool UseCardMarkingForAllocation(const intptr_t array_length)
Definition: object.h:10818
ObjectPtr At(intptr_t index) const
Definition: object.h:10875
intptr_t Length() const
Definition: object.h:10829
static ArrayPtr MakeFixedLength(const GrowableObjectArray &growable_array, bool unique=false)
Definition: object.cc:24935
void SetAt(intptr_t index, const Object &value) const
Definition: object.h:10880
static ArrayPtr Grow(const Array &source, intptr_t new_length, Heap::Space space=Heap::kNew)
Definition: object.cc:24853
void Add(const T &value)
intptr_t length() const
static const Bool & False()
Definition: object.h:10799
static const Bool & True()
Definition: object.h:10797
StringPtr target_name() const
Definition: object.h:2372
ArrayPtr arguments_descriptor() const
Definition: object.h:2373
static constexpr Register kReturnReg
static AbstractTypePtr FinalizeType(const AbstractType &type, FinalizationKind finalization=kCanonicalize)
static bool ProcessPendingClasses()
static void FinalizeTypesInClass(const Class &cls)
static void FinalizeClass(const Class &cls)
void set_is_implemented_unsafe() const
Definition: object.cc:5618
FunctionPtr InvocationDispatcherFunctionFromIndex(intptr_t idx) const
Definition: object.cc:3419
void Finalize() const
Definition: object.cc:4307
void SetFields(const Array &value) const
Definition: object.cc:4984
TypePtr super_type() const
Definition: object.h:1431
FunctionPtr GetInvocationDispatcher(const String &target_name, const Array &args_desc, UntaggedFunction::Kind kind, bool create_if_absent) const
Definition: object.cc:3847
FunctionPtr LookupStaticFunction(const String &name) const
Definition: object.cc:6137
intptr_t id() const
Definition: object.h:1233
void set_interfaces(const Array &value) const
Definition: object.cc:5739
ArrayPtr fields() const
Definition: object.h:1615
void set_is_declaration_loaded_unsafe() const
Definition: object.cc:5632
intptr_t implementor_cid() const
Definition: object.h:1245
intptr_t host_instance_size() const
Definition: object.h:1143
StringPtr Name() const
Definition: object.cc:2977
ErrorPtr EnsureIsFinalized(Thread *thread) const
Definition: object.cc:4924
void set_is_synthesized_class_unsafe() const
Definition: object.cc:5651
static ClassPtr New(IsolateGroup *isolate_group, bool register_class=true)
Definition: object.cc:3053
TokenPosition end_token_pos() const
Definition: object.h:1291
FieldPtr LookupField(const String &name) const
Definition: object.cc:6352
void set_library(const Library &value) const
Definition: object.cc:3438
bool is_implemented() const
Definition: object.h:1692
void SetFunctions(const Array &value) const
Definition: object.cc:3264
intptr_t FindInvocationDispatcherFunctionIndex(const Function &needle) const
Definition: object.cc:3392
ArrayPtr current_functions() const
Definition: object.h:1641
ScriptPtr script() const
Definition: object.h:1272
static intptr_t FindClosureIndex(const Function &needle)
static void AddClosureFunctionLocked(const Function &function, bool allow_implicit_closure_functions=false)
static FunctionPtr ClosureFunctionFromIndex(intptr_t idx)
static ClosurePtr New(const TypeArguments &instantiator_type_arguments, const TypeArguments &function_type_arguments, const Function &function, const Object &context, Heap::Space space=Heap::kNew)
Definition: object.cc:25942
static void SetInstructions(const Code &code, const Instructions &instructions, uword unchecked_offset)
static CodePtr FinalizeCodeAndNotify(const Function &function, FlowGraphCompiler *compiler, compiler::Assembler *assembler, PoolAttachment pool_attachment, bool optimized=false, CodeStatistics *stats=nullptr)
Definition: object.cc:17983
static ErrorPtr EnsureUnoptimizedCode(Thread *thread, const Function &function)
Definition: compiler.cc:854
static ObjectPtr CompileOptimizedFunction(Thread *thread, const Function &function, intptr_t osr_id=kNoOSRDeoptId)
Definition: compiler.cc:886
static ConstMapPtr NewUninitialized(Heap::Space space=Heap::kNew)
Definition: object.cc:25241
static ConstSetPtr NewUninitialized(Heap::Space space=Heap::kNew)
Definition: object.cc:25289
static ContextPtr New(intptr_t num_variables, Heap::Space space=Heap::kNew)
Definition: object.cc:18511
void set_parent(const Context &parent) const
Definition: object.h:7407
void SetAt(intptr_t context_index, const Object &value) const
Definition: object.h:13303
ObjectPtr At(intptr_t context_index) const
Definition: object.h:7422
intptr_t num_variables() const
Definition: object.h:7414
ContextPtr parent() const
Definition: object.h:7406
static ObjectPtr InvokeFunction(const Function &function, const Array &arguments)
Definition: dart_entry.cc:31
static ThreadPool * thread_pool()
Definition: dart.h:73
virtual bool OperatorEquals(const Instance &other) const
Definition: object.cc:23378
virtual bool CanonicalizeEquals(const Instance &other) const
Definition: object.cc:23388
static DoublePtr New(double d, Heap::Space space=Heap::kNew)
Definition: object.cc:23402
double value() const
Definition: object.h:10115
static DoublePtr NewCanonical(double d)
Definition: object.cc:23418
intptr_t OuterTryIndex(intptr_t try_index) const
Definition: object.cc:16201
bool HasCatchAll(intptr_t try_index) const
Definition: object.cc:16216
void GetHandlerInfo(intptr_t try_index, ExceptionHandlerInfo *info) const
Definition: object.cc:16189
uword HandlerPCOffset(intptr_t try_index) const
Definition: object.cc:16196
bool NeedsStackTrace(intptr_t try_index) const
Definition: object.cc:16206
void SetHandlerInfo(intptr_t try_index, intptr_t outer_try_index, uword handler_pc_offset, bool needs_stacktrace, bool has_catch_all, bool is_generated) const
Definition: object.cc:16168
intptr_t num_entries() const
Definition: object.cc:16153
static ExceptionHandlersPtr New(intptr_t num_handlers)
Definition: object.cc:16241
static ExternalTypedDataPtr New(intptr_t class_id, uint8_t *data, intptr_t len, Heap::Space space=Heap::kNew, bool perform_eager_msan_initialization_check=true)
Definition: object.cc:25626
static StringPtr NameFromSetter(const String &setter_name)
Definition: object.cc:11821
static bool IsGetterName(const String &function_name)
Definition: object.cc:11831
static bool IsSetterName(const String &function_name)
Definition: object.cc:11835
StringPtr name() const
Definition: object.h:4430
intptr_t HostOffset() const
Definition: object.h:13241
static StringPtr GetterName(const String &field_name)
Definition: object.cc:11792
static StringPtr SetterName(const String &field_name)
Definition: object.cc:11804
static StringPtr NameFromGetter(const String &getter_name)
Definition: object.cc:11816
FinalizerEntryPtr next() const
Definition: object.h:12996
static FinalizerEntryPtr New(const FinalizerBase &finalizer, Heap::Space space=Heap::kNew)
Definition: object.cc:26862
static FinalizerPtr New(Heap::Space space=Heap::kNew)
Definition: object.cc:26782
void set_result_type(const AbstractType &value) const
Definition: object.cc:8575
void set_num_fixed_parameters(intptr_t value) const
Definition: object.cc:11608
void SetNumOptionalParameters(intptr_t num_optional_parameters, bool are_optional_positional) const
Definition: object.cc:11617
static FunctionTypePtr New(intptr_t num_parent_type_arguments=0, Nullability nullability=Nullability::kNonNullable, Heap::Space space=Heap::kOld)
Definition: object.cc:11631
bool CanBeInlined() const
Definition: object.cc:9199
static FunctionPtr New(const FunctionType &signature, const String &name, UntaggedFunction::Kind kind, bool is_static, bool is_const, bool is_abstract, bool is_external, bool is_native, const Object &owner, TokenPosition token_pos, Heap::Space space=Heap::kOld)
Definition: object.cc:10243
int32_t SourceFingerprint() const
Definition: object.cc:11169
void set_unoptimized_code(const Code &value) const
Definition: object.cc:8038
static FunctionPtr NewClosureFunction(const String &name, const Function &parent, TokenPosition token_pos)
Definition: object.cc:10348
TypeParameterPtr TypeParameterAt(intptr_t index, Nullability nullability=Nullability::kNonNullable) const
Definition: object.cc:8881
void Add(const Object &value, Heap::Space space=Heap::kNew) const
Definition: object.cc:24991
static GrowableObjectArrayPtr New(Heap::Space space=Heap::kNew)
Definition: object.h:11144
intptr_t Length() const
Definition: object.h:11072
ObjectPtr At(intptr_t index) const
Definition: object.h:11085
void SetAt(intptr_t index, const Object &value) const
Definition: object.h:11091
intptr_t Capacity() const
Definition: object.h:11067
bool AllocatedExternal(intptr_t size, Space space)
Definition: heap.cc:180
@ kNew
Definition: heap.h:38
@ kOld
Definition: heap.h:39
intptr_t CapacityInWords(Space space) const
Definition: heap.cc:806
void AddReceiverCheck(intptr_t receiver_class_id, const Function &target, intptr_t count=1, StaticTypeExactnessState exactness=StaticTypeExactnessState::NotTracking()) const
Definition: object.cc:16889
intptr_t deopt_id() const
Definition: object.h:2468
intptr_t NumberOfUsedChecks() const
Definition: object.cc:16640
void GetOneClassCheckAt(intptr_t index, intptr_t *class_id, Function *target) const
Definition: object.cc:16989
intptr_t NumArgsTested() const
Definition: object.cc:16471
static ICDataPtr NewForStaticCall(const Function &owner, const Function &target, const Array &arguments_descriptor, intptr_t deopt_id, intptr_t num_args_tested, RebindRule rebind_rule)
Definition: object.cc:17401
void AddCheck(const GrowableArray< intptr_t > &class_ids, const Function &target, intptr_t count=1) const
Definition: object.cc:16784
FunctionPtr GetTargetAt(intptr_t index) const
Definition: object.cc:17029
void GetCheckAt(intptr_t index, GrowableArray< intptr_t > *class_ids, Function *target) const
Definition: object.cc:16955
intptr_t GetCidAt(intptr_t index) const
Definition: object.cc:17004
intptr_t NumberOfChecks() const
Definition: object.cc:16577
FunctionPtr Owner() const
Definition: object.cc:16423
void SetCountAt(intptr_t index, intptr_t value) const
Definition: object.cc:17050
bool IsIdenticalTo(const Instance &other) const
Definition: object.cc:20861
static intptr_t ElementSizeFor(intptr_t cid)
Definition: object.cc:20967
virtual bool OperatorEquals(const Instance &other) const
Definition: object.cc:20855
static InstancePtr New(const Class &cls, Heap::Space space=Heap::kNew)
Definition: object.cc:20935
static InstructionsPtr FromPayloadStart(uword payload_start)
Definition: object.h:5846
uword PayloadStart() const
Definition: object.h:5745
static IntegerPtr New(const String &str, Heap::Space space=Heap::kNew)
Definition: object.cc:22984
static IntegerPtr NewCanonical(const String &str)
Definition: object.cc:22999
virtual bool Equals(const Instance &other) const
Definition: object.cc:23034
Heap * heap() const
Definition: isolate.h:296
ObjectStore * object_store() const
Definition: isolate.h:510
static IsolateGroup * Current()
Definition: isolate.h:539
static Isolate * Current()
Definition: isolate.h:986
MessageHandler * message_handler() const
Definition: isolate.cc:2416
void set_finalizers(const GrowableObjectArray &value)
Definition: isolate.cc:2001
static LibraryPtr CoreLibrary()
Definition: object.cc:14787
void AddObject(const Object &obj, const String &name) const
Definition: object.cc:13815
ObjectPtr GetMetadata(const Object &declaration) const
Definition: object.cc:13654
void AddClass(const Class &cls) const
Definition: object.cc:13914
FunctionPtr LookupFunctionAllowPrivate(const String &name) const
Definition: object.cc:14084
static LibraryPtr AsyncLibrary()
Definition: object.cc:14779
ClassPtr LookupClass(const String &name) const
Definition: object.cc:14105
static LibraryPtr LookupLibrary(Thread *thread, const String &url)
Definition: object.cc:14599
FieldPtr LookupFieldAllowPrivate(const String &name) const
Definition: object.cc:14075
static const LinkedHashBase & Cast(const Object &obj)
Definition: object.h:12010
int context_level() const
Definition: scopes.h:333
int NumCapturedVariables() const
Definition: scopes.cc:409
int function_level() const
Definition: scopes.h:322
static LocalScope * RestoreOuterScope(const ContextScope &context_scope)
Definition: scopes.cc:518
VariableIndex AllocateVariables(const Function &function, VariableIndex first_parameter_index, int num_parameters, VariableIndex first_local_index, LocalScope *context_owner, bool *found_captured_variables)
Definition: scopes.cc:133
intptr_t num_variables() const
Definition: scopes.h:397
LocalVariable * LookupVariable(const String &name, intptr_t kernel_offset, bool test_only)
Definition: scopes.cc:350
bool AddVariable(LocalVariable *variable)
Definition: scopes.cc:57
ContextScopePtr PreserveOuterScope(const Function &function, intptr_t current_context_level) const
Definition: scopes.cc:433
LocalVariable * LocalLookupVariable(const String &name, intptr_t kernel_offset) const
Definition: scopes.cc:336
VariableIndex index() const
Definition: scopes.h:202
LocalScope * owner() const
Definition: scopes.h:122
bool is_captured() const
Definition: scopes.h:143
static constexpr intptr_t kNoKernelOffset
Definition: scopes.h:77
static MapPtr NewDefault(intptr_t class_id=kMapCid, Heap::Space space=Heap::kNew)
Definition: object.cc:25090
intptr_t Length() const
Definition: message.cc:191
virtual int CompareWith(const Integer &other) const
Definition: object.cc:23348
static constexpr int64_t kMinValue
Definition: object.h:10070
int64_t value() const
Definition: object.h:10073
ObjectPtr referent() const
Definition: object.h:13120
void set_referent(const Object &referent) const
Definition: object.h:13122
static MirrorReferencePtr New(const Object &referent, Heap::Space space=Heap::kNew)
Definition: object.cc:26916
static NativeFinalizerPtr New(Heap::Space space=Heap::kNew)
Definition: object.cc:26798
static void static void PrintErr(const char *format,...) PRINTF_ATTRIBUTE(1
static char * SCreate(Zone *zone, const char *format,...) PRINTF_ATTRIBUTE(2
virtual void VisitObject(ObjectPtr obj)
ObjectAccumulator(GrowableArray< Object * > *objects)
static ObjectPoolPtr NewFromBuilder(const compiler::ObjectPoolBuilder &builder)
Definition: object.cc:15676
bool IsFreeListElement() const
UntaggedObject * untag() const
intptr_t GetClassIdMayBeSmi() const
@ kScrubbedName
Definition: object.h:633
void PrintJSON(JSONStream *stream, bool ref=true) const
static ObjectPtr null()
Definition: object.h:433
ObjectPtr ptr() const
Definition: object.h:332
virtual const char * ToCString() const
Definition: object.h:366
bool IsNull() const
Definition: object.h:363
static Object & Handle()
Definition: object.h:407
static ObjectPtr RawCast(ObjectPtr obj)
Definition: object.h:325
static ClassPtr void_class()
Definition: object.h:515
static Object & ZoneHandle()
Definition: object.h:419
static ClassPtr dynamic_class()
Definition: object.h:514
static OneByteStringPtr New(intptr_t len, Heap::Space space)
Definition: object.cc:24368
static OneByteStringPtr null()
Definition: object.h:10624
intptr_t YieldIndex() const
Definition: object.h:6160
TokenPosition TokenPos() const
Definition: object.h:6156
intptr_t DeoptId() const
Definition: object.h:6155
intptr_t TryIndex() const
Definition: object.h:6159
UntaggedPcDescriptors::Kind Kind() const
Definition: object.h:6161
static PointerPtr New(uword native_address, Heap::Space space=Heap::kNew)
Definition: object.cc:25726
uint64_t NextUInt64()
Definition: random.h:26
static FunctionPtr ResolveDynamicFunction(Zone *zone, const Class &receiver_class, const String &function_name)
Definition: resolver.cc:176
static FunctionPtr ResolveFunction(Zone *zone, const Class &receiver_class, const String &function_name)
Definition: resolver.cc:167
static ScriptPtr New(const String &url, const String &source)
Definition: object.cc:13451
bool GetTokenLocation(const TokenPosition &token_pos, intptr_t *line, intptr_t *column=nullptr) const
Definition: object.cc:13283
static SetPtr NewDefault(intptr_t class_id=kSetCid, Heap::Space space=Heap::kNew)
Definition: object.cc:25266
static SmiPtr New(intptr_t value)
Definition: object.h:10006
intptr_t Value() const
Definition: object.h:9990
virtual bool Equals(const Instance &other) const
Definition: object.cc:23251
virtual int64_t AsInt64Value() const
Definition: object.cc:23262
virtual int CompareWith(const Integer &other) const
Definition: object.cc:23270
static bool IsValid(int64_t value)
Definition: object.h:10026
virtual double AsDoubleValue() const
Definition: object.cc:23258
static StringPtr FromLatin1(const uint8_t *latin1_array, intptr_t array_len, Heap::Space space=Heap::kNew)
Definition: object.cc:23733
static StringPtr NewFormatted(const char *format,...) PRINTF_ATTRIBUTE(1
Definition: object.cc:24004
bool IsOneByteString() const
Definition: object.h:10311
intptr_t Length() const
Definition: object.h:10210
virtual ObjectPtr HashCode() const
Definition: object.h:10257
static uword HashConcat(const String &str1, const String &str2)
Definition: object.cc:23485
static StringPtr ConcatAll(const Array &strings, Heap::Space space=Heap::kNew)
Definition: object.cc:24048
static const char * ScrubName(const String &name, bool is_extension=false)
Definition: object.cc:287
bool Equals(const String &str) const
Definition: object.h:13337
static StringPtr New(const char *cstr, Heap::Space space=Heap::kNew)
Definition: object.cc:23698
intptr_t CompareTo(const String &other) const
Definition: object.cc:23638
bool IsTwoByteString() const
Definition: object.h:10315
uint16_t CharAt(intptr_t index) const
Definition: object.h:10259
static StringPtr SubString(const String &str, intptr_t begin_index, Heap::Space space=Heap::kNew)
Definition: object.cc:24080
bool StartsWith(const String &other) const
Definition: object.h:10298
static StringPtr EscapeSpecialCharacters(const String &str)
Definition: object.cc:23861
static StringPtr Concat(const String &str1, const String &str2, Heap::Space space=Heap::kNew)
Definition: object.cc:24037
static StringPtr DecodeIRI(const String &str)
Definition: object.cc:23948
bool IsSymbol() const
Definition: object.h:10309
static StringPtr FromUTF16(const uint16_t *utf16_array, intptr_t array_len, Heap::Space space=Heap::kNew)
Definition: object.cc:23739
uword Hash() const
Definition: object.h:10216
bool EqualsLatin1(const uint8_t *characters, intptr_t len) const
Definition: object.h:10274
static bool EqualsIgnoringPrivateKey(const String &str1, const String &str2)
Definition: object.cc:24299
static const char * EncodeIRI(const String &str)
Definition: object.cc:23918
static StringPtr FromUTF32(const int32_t *utf32_array, intptr_t array_len, Heap::Space space=Heap::kNew)
Definition: object.cc:23755
static StringPtr FromUTF8(const uint8_t *utf8_array, intptr_t array_len, Heap::Space space=Heap::kNew)
Definition: object.cc:23705
static SubtypeTestCachePtr New(intptr_t num_inputs)
Definition: object.cc:18924
static constexpr intptr_t kMaxInputs
Definition: object.h:7705
@ kInstanceDelayedFunctionTypeArguments
Definition: object.h:7694
@ kInstanceParentFunctionTypeArguments
Definition: object.h:7693
static constexpr intptr_t kMaxLinearCacheEntries
Definition: object.h:7830
static StringPtr FromUTF16(Thread *thread, const uint16_t *utf16_array, intptr_t len)
Definition: symbols.cc:229
static StringPtr FromConcatAll(Thread *thread, const GrowableHandlePtrArray< const String > &strs)
Definition: symbols.cc:262
static const String & Empty()
Definition: symbols.h:688
static StringPtr New(Thread *thread, const char *cstr)
Definition: symbols.h:723
static const String & Dot()
Definition: symbols.h:613
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:436
static Dart_Handle ReloadTestScript(const char *script)
Definition: unit_test.cc:613
static const char * url()
Definition: unit_test.cc:185
bool Run(Args &&... args)
Definition: thread_pool.h:45
Zone * zone() const
Definition: thread_state.h:37
static Thread * Current()
Definition: thread.h:362
Isolate * isolate() const
Definition: thread.h:534
IsolateGroup * isolate_group() const
Definition: thread.h:541
ToggleBreakpointTask(IsolateGroup *isolate_group, Dart_Isolate isolate, std::atomic< bool > *done)
intptr_t Pos() const
static TokenPosition Deserialize(int32_t value)
static const TokenPosition kMinSource
static TwoByteStringPtr New(intptr_t len, Heap::Space space)
Definition: object.cc:24562
static SmiPtr Sentinel()
Definition: object.cc:7173
static constexpr intptr_t kMaxLinearCacheEntries
Definition: object.h:8933
bool Equals(const TypeArguments &other) const
Definition: object.h:8686
void SetTypeAt(intptr_t index, const AbstractType &value) const
Definition: object.cc:7323
TypeArgumentsPtr Canonicalize(Thread *thread) const
Definition: object.cc:7703
static TypeArgumentsPtr New(intptr_t len, Heap::Space space=Heap::kOld)
Definition: object.cc:7675
static TypePtr IntType()
static TypePtr VoidType()
static TypePtr Double()
static TypePtr StringType()
static TypePtr BoolType()
static TypePtr SmiType()
static TypePtr DynamicType()
static TypePtr New(const Class &clazz, const TypeArguments &arguments, Nullability nullability=Nullability::kNonNullable, Heap::Space space=Heap::kOld)
static TypePtr NewNonParameterizedType(const Class &type_class)
intptr_t Length() const
Definition: object.h:11518
static TypedDataPtr Grow(const TypedData &current, intptr_t len, Heap::Space space=Heap::kNew)
Definition: object.cc:25601
static intptr_t MaxElements(intptr_t class_id)
Definition: object.h:11684
static TypedDataPtr New(intptr_t class_id, intptr_t len, Heap::Space space=Heap::kNew)
Definition: object.cc:25587
static ObjectPtr FromAddr(uword addr)
Definition: raw_object.h:516
static uword ToAddr(const UntaggedObject *raw_obj)
Definition: raw_object.h:522
intptr_t HeapSize() const
Definition: raw_object.h:401
static int SNPrint(char *str, size_t size, const char *format,...) PRINTF_ATTRIBUTE(3
static constexpr T RoundUp(T x, uintptr_t alignment, uintptr_t offset=0)
Definition: utils.h:120
Definition: il.h:75
int value() const
Definition: scopes.h:69
void SetAt(intptr_t index, const Object &value) const
Definition: object.h:6723
intptr_t Length() const
Definition: object.h:6697
ObjectPtr At(intptr_t index) const
Definition: object.h:6722
static WeakArrayPtr New(intptr_t length, Heap::Space space=Heap::kNew)
Definition: object.cc:17533
ObjectPtr value() const
Definition: object.h:12924
static WeakPropertyPtr New(Heap::Space space=Heap::kNew)
Definition: object.cc:26756
void set_key(const Object &key) const
Definition: object.h:12921
ObjectPtr key() const
Definition: object.h:12920
void set_value(const Object &value) const
Definition: object.h:12925
static WeakReferencePtr New(Heap::Space space=Heap::kNew)
Definition: object.cc:26766
static void SetNativeResolver(BuiltinLibraryId id)
Definition: builtin.cc:28
static void SetNativeResolver()
#define THR_Print(format,...)
Definition: log.h:20
struct _Dart_Handle * Dart_Handle
Definition: dart_api.h:258
struct _Dart_Isolate * Dart_Isolate
Definition: dart_api.h:88
struct _Dart_NativeArguments * Dart_NativeArguments
Definition: dart_api.h:3019
void(* Dart_NativeFunction)(Dart_NativeArguments arguments)
Definition: dart_api.h:3207
#define FAIL(name, result)
#define ASSERT(E)
VkInstance instance
Definition: main.cc:48
SkBitmap source
Definition: examples.cpp:28
static bool b
struct MyStruct a[10]
EMSCRIPTEN_KEEPALIVE void empty()
#define FATAL(error)
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
static const char * expected_value
const uint8_t uint32_t uint32_t GError ** error
uint8_t value
GAsyncResult * result
uint32_t * target
Dart_NativeFunction function
Definition: fuchsia.cc:51
int argument_count
Definition: fuchsia.cc:52
#define HANDLESCOPE(thread)
Definition: handles.h:321
static float max(float r, float g, float b)
Definition: hsl.cpp:49
size_t length
static constexpr intptr_t kWordSize
Definition: runtime_api.h:274
bool IsSmi(int64_t v)
Definition: runtime_api.cc:31
Definition: dart_vm.cc:33
constexpr int64_t kMaxInt64
Definition: globals.h:486
const int kNumTypedDataCidRemainders
Definition: class_id.h:265
static bool Equals(const Object &expected, const Object &actual)
static const ClassId kLastTypedDataCid
Definition: class_id.h:378
static CodePtr CreateInvokeInstantiateTypeArgumentsStub(Thread *thread)
constexpr intptr_t MB
Definition: globals.h:530
static void GenerateInvokeInstantiateTAVStub(compiler::Assembler *assembler)
bool IsTypedDataClassId(intptr_t index)
Definition: class_id.h:433
void ElideJSONSubstring(const char *prefix, const char *in, char *out, const char *postfix)
Definition: unit_test.cc:790
static MapPtr ConstructImmutableMap(const Array &input_data, intptr_t used_data, const TypeArguments &type_arguments)
static void WeakReference_Preserve_ReachableThroughWeakProperty(Thread *thread, Heap::Space space)
static void Finalizer_GcFinalizer(Thread *thread, Heap::Space space)
static void SubtypeTestCacheEntryTest(Thread *thread, const SubtypeTestCache &cache, const Object &instance_class_id_or_signature, const AbstractType &destination_type, const TypeArguments &instance_type_arguments, const TypeArguments &instantiator_type_arguments, const TypeArguments &function_type_arguments, const TypeArguments &parent_function_type_arguments, const TypeArguments &delayed_type_arguments, const Bool &expected_result, Bool *got_result)
void SetBreakpoint(Dart_NativeArguments args)
ISOLATE_UNIT_TEST_CASE_WITH_EXPECTATION(SafepointOperation_NonDeoptAndDeoptNesting, "Crash")
DART_EXPORT void Dart_EnterScope()
static void CheckSubtypeRelation(const Expect &expect, const AbstractType &sub, const AbstractType &super, bool is_subtype)
const char *const name
static void ExpectTypesEquivalent(const Expect &expect, const AbstractType &expected, const AbstractType &got, TypeEquality kind)
bool IsConcreteTypeClassId(intptr_t index)
Definition: class_id.h:325
const intptr_t kFinalizerTwoEntriesNumObjects
DART_EXPORT void Dart_EnterIsolate(Dart_Isolate isolate)
static void Finalizer_ClearDetachOne(Thread *thread, Heap::Space space)
CAllocUniquePtr< char > CStringUniquePtr
Definition: utils.h:31
DART_EXPORT Dart_Handle Dart_Invoke(Dart_Handle target, Dart_Handle name, int number_of_arguments, Dart_Handle *arguments)
static void HashMapNonConstEqualsConst(const char *script, bool check_data=true)
Nullability
Definition: object.h:1112
static Dart_WeakPersistentHandle weak1
static void TestIllegalTypedDataLength(const char *class_name, intptr_t length)
static void Finalizer_ClearValueOne(Thread *thread, Heap::Space space, bool null_token)
static void Finalizer_PreserveOne(Thread *thread, Heap::Space space, bool with_detach)
static FieldPtr GetField(const Class &cls, const char *name)
static void FinalizeAndCanonicalize(AbstractType *type)
static void PrintMetadata(const char *name, const Object &data)
const char *const class_name
Dart_Handle Dart_RemoveBreakpoint(Dart_Handle breakpoint_id_in)
DART_EXPORT Dart_Handle Dart_NewInteger(int64_t value)
int32_t classid_t
Definition: globals.h:524
static void Finalizer_TwoEntriesCrossGen(Thread *thread, Heap::Space *spaces, bool collect_old_space, bool collect_new_space, bool evacuate_new_space_and_collect_old_space, bool clear_value_1, bool clear_value_2, bool clear_detach_1, bool clear_detach_2)
constexpr uint64_t kMaxUint64
Definition: globals.h:487
@ kIllegalCid
Definition: class_id.h:214
@ kNullCid
Definition: class_id.h:252
@ kDynamicCid
Definition: class_id.h:253
ObjectPtr Invoke(const Library &lib, const char *name)
constexpr intptr_t kWordSizeLog2
Definition: globals.h:507
FunctionPtr GetFunction(const Library &lib, const char *name)
static bool HashCodeEqualsCanonicalizeHash(const char *value_script, uint32_t hashcode_canonicalize_vm=kCalculateCanonicalizeHash, bool check_identity=true, bool check_hashcode=true)
static FunctionPtr GetDummyTarget(const char *name)
static void CheckConcatAll(const String *data[], intptr_t n)
bool EqualsIgnoringPrivate(const String &name, const String &private_name)
uintptr_t uword
Definition: globals.h:501
intptr_t word
Definition: globals.h:500
DART_EXPORT Dart_Isolate Dart_CurrentIsolate()
static void TypeArgumentsHashCacheTest(Thread *thread, intptr_t num_classes)
TypeEquality
Definition: object.h:1118
DART_EXPORT bool Dart_IsError(Dart_Handle handle)
static void SubtypeTestCacheTest(Thread *thread, intptr_t num_classes, bool expect_hash)
static void SubtypeTestCacheCheckContents(Zone *zone, const SubtypeTestCache &cache)
AsThreadStackResource< RawReloadParticipationScope > ReloadParticipationScope
Definition: thread.h:1634
static ClassPtr CreateDummyClass(const String &class_name, const Script &script)
Definition: object_test.cc:44
static const ClassId kFirstTypedDataCid
Definition: class_id.h:377
static constexpr int kCallerSpSlotFromFp
DART_EXPORT Dart_Isolate Dart_CreateIsolateInGroup(Dart_Isolate group_member, const char *name, Dart_IsolateShutdownCallback shutdown_callback, Dart_IsolateCleanupCallback cleanup_callback, void *child_isolate_data, char **error)
DART_EXPORT bool Dart_RunLoopAsync(bool errors_are_fatal, Dart_Port on_error_port, Dart_Port on_exit_port, char **error)
static void HashSetNonConstEqualsConst(const char *script, bool check_data=true)
ISOLATE_UNIT_TEST_CASE(StackAllocatedDestruction)
DART_EXPORT Dart_Handle Dart_SetNativeResolver(Dart_Handle library, Dart_NativeEntryResolver resolver, Dart_NativeEntrySymbol symbol)
DART_EXPORT void Dart_ExitIsolate()
const Register FPREG
ClassPtr GetClass(const Library &lib, const char *name)
const intptr_t cid
const uint32_t kCalculateCanonicalizeHash
static void WeakReference_PreserveOne(Thread *thread, Heap::Space space)
TEST_CASE(DirectoryCurrent)
Dart_Handle NewString(const char *str)
static void WeakReference_ClearOne(Thread *thread, Heap::Space space)
static void NativeFinalizer_TwoEntriesCrossGen(Thread *thread, Heap::Space *spaces, bool collect_new_space, bool evacuate_new_space_and_collect_old_space, bool clear_value_1, bool clear_value_2, bool clear_detach_1, bool clear_detach_2)
static bool IsLinkedHashBase(const Object &object)
static uint32_t Hash(uint32_t key)
Definition: hashmap_test.cc:65
bool TESTING_runtime_fail_on_existing_cache_entry
Definition: object.cc:7617
DART_EXPORT void Dart_ExitScope()
constexpr int32_t kMaxInt32
Definition: globals.h:483
static LibraryPtr CreateDummyLibrary(const String &library_name)
DART_EXPORT Dart_Handle Dart_ListLength(Dart_Handle list, intptr_t *len)
static FieldPtr CreateTestField(const char *name)
constexpr intptr_t kWordSize
Definition: globals.h:509
static SetPtr ConstructImmutableSet(const Array &input_data, intptr_t used_data, const TypeArguments &type_arguments)
static constexpr intptr_t kObjectAlignment
static FunctionPtr CreateFunction(const char *name)
static void CollectAllGarbage(Thread *thread, JSONStream *js)
Definition: service.cc:4559
static ClassPtr CreateTestClass(const char *name)
static void HashBaseNonConstEqualsConst(const char *script, bool check_data=true)
static void Finalizer_DetachOne(Thread *thread, Heap::Space space, bool clear_value)
const char *const function_name
static int8_t data[kExtLength]
DART_EXPORT Dart_Handle Dart_StringToCString(Dart_Handle object, const char **cstr)
static void TestIllegalArrayLength(intptr_t length)
static FunctionPtr GetStaticFunction(const Class &cls, const char *name)
Dart_Handle Dart_SetBreakpoint(Dart_Handle script_url_in, intptr_t line_number)
const intptr_t kSmiMin
Definition: globals.h:29
void StripTokenPositions(char *buffer)
Definition: unit_test.cc:813
static void Finalizer_TwoEntries(Thread *thread, Heap::Space space, bool clear_value_1, bool clear_value_2, bool clear_detach_1, bool clear_detach_2)
static bool LinkedHashBaseEqual(const LinkedHashBase &map1, const LinkedHashBase &map2, bool print_diff, bool check_data=true)
static int NumEntries(const FinalizerEntry &entry, intptr_t acc=0)
void NativeFinalizer_TwoEntriesCrossGen_Finalizer(void *peer)
static Dart_WeakPersistentHandle weak2
static Dart_NativeFunction SetBreakpointResolver(Dart_Handle name, int argument_count, bool *auto_setup_scope)
@ kCurrentAndEnclosingFree
Definition: object.h:2937
@ kAllFree
Definition: object.h:2940
static void WeakReference_Clear_ReachableThroughWeakProperty(Thread *thread, Heap::Space space)
static TypePtr CreateFutureOrType(const AbstractType &param, Nullability nullability)
DECLARE_FLAG(bool, show_invisible_frames)
static TypePtr CreateFutureType(const AbstractType &param, Nullability nullability)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace Enable an endless trace buffer The default is a ring buffer This is useful when very old events need to viewed For during application launch Memory usage will continue to grow indefinitely however Start app with an specific route defined on the framework flutter assets Path to the Flutter assets directory enable service port Allow the VM service to fallback to automatic port selection if binding to a specified port fails trace Trace early application lifecycle Automatically switches to an endless trace buffer trace skia Filters out all Skia trace event categories except those that are specified in this comma separated list dump skp on shader Automatically dump the skp that triggers new shader compilations This is useful for writing custom ShaderWarmUp to reduce jank By this is not enabled to reduce the overhead purge persistent cache
Definition: switches.h:191
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
Definition: switches.h:126
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not set
Definition: switches.h:76
std::function< void()> closure
Definition: closure.h:14
SI auto map(std::index_sequence< I... >, Fn &&fn, const Args &... args) -> skvx::Vec< sizeof...(I), decltype(fn(args[0]...))>
Definition: SkVx.h:680
#define __
#define EXPECT_SUBTYPE(sub, super)
#define USED_INPUT_CASE(Input, ExpectedCids)
#define Z
Definition: object_test.cc:40
#define EXPECT_TYPES_EQUAL(expected, got)
#define FINALIZER_CROSS_GEN_TEST_CASE(n)
#define EXPECT_NOT_SUBTYPE(sub, super)
#define EXPECT_TYPES_SYNTACTICALLY_EQUIVALENT(expected, got)
#define REPEAT_512(V)
#define FINALIZER_NATIVE_CROSS_GEN_TEST_CASE(n)
#define Px32
Definition: globals.h:414
#define FALL_THROUGH
Definition: globals.h:15
#define Px
Definition: globals.h:410
#define DART_2PART_UINT64_C(a, b)
Definition: globals.h:472
#define DEBUG_ONLY(code)
Definition: globals.h:141
#define Pd64
Definition: globals.h:416
#define Px64
Definition: globals.h:418
#define Pd
Definition: globals.h:408
#define DART_INT64_C(x)
Definition: globals.h:433
#define Pd32
Definition: globals.h:412
static constexpr Register kInstantiatorTypeArgumentsReg
static constexpr Register kUninstantiatedTypeArgumentsReg
static constexpr Register kResultTypeArgumentsReg
static constexpr Register kFunctionTypeArgumentsReg
const char * out
const char * in
#define EXPECT_ERROR(handle, substring)
Definition: unit_test.h:663
#define EXPECT_NULL(handle)
Definition: unit_test.h:694
#define EXPECT_TRUE(handle)
Definition: unit_test.h:678
#define EXPECT_VALID(handle)
Definition: unit_test.h:643
#define ARRAY_SIZE(array)
Definition: globals.h:72