OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/dart_api_impl.h" | 5 #include "vm/dart_api_impl.h" |
6 #include "bin/builtin.h" | 6 #include "bin/builtin.h" |
7 #include "include/dart_api.h" | 7 #include "include/dart_api.h" |
8 #include "include/dart_mirrors_api.h" | 8 #include "include/dart_mirrors_api.h" |
9 #include "include/dart_native_api.h" | 9 #include "include/dart_native_api.h" |
10 #include "include/dart_tools_api.h" | 10 #include "include/dart_tools_api.h" |
11 #include "platform/assert.h" | 11 #include "platform/assert.h" |
12 #include "platform/text_buffer.h" | 12 #include "platform/text_buffer.h" |
13 #include "platform/utils.h" | 13 #include "platform/utils.h" |
14 #include "vm/class_finalizer.h" | 14 #include "vm/class_finalizer.h" |
15 #include "vm/compiler.h" | 15 #include "vm/compiler.h" |
16 #include "vm/dart_api_state.h" | 16 #include "vm/dart_api_state.h" |
17 #include "vm/lockers.h" | 17 #include "vm/lockers.h" |
18 #include "vm/timeline.h" | 18 #include "vm/timeline.h" |
19 #include "vm/unit_test.h" | 19 #include "vm/unit_test.h" |
20 #include "vm/verifier.h" | 20 #include "vm/verifier.h" |
21 | 21 |
22 namespace dart { | 22 namespace dart { |
23 | 23 |
24 DECLARE_FLAG(bool, verify_acquired_data); | 24 DECLARE_FLAG(bool, verify_acquired_data); |
25 DECLARE_FLAG(bool, ignore_patch_signature_mismatch); | 25 DECLARE_FLAG(bool, ignore_patch_signature_mismatch); |
26 DECLARE_FLAG(bool, support_externalizable_strings); | |
27 DECLARE_FLAG(bool, use_dart_frontend); | 26 DECLARE_FLAG(bool, use_dart_frontend); |
28 | 27 |
29 #ifndef PRODUCT | 28 #ifndef PRODUCT |
30 | 29 |
31 TEST_CASE(DartAPI_ErrorHandleBasics) { | 30 TEST_CASE(DartAPI_ErrorHandleBasics) { |
32 const char* kScriptChars = | 31 const char* kScriptChars = |
33 "void testMain() {\n" | 32 "void testMain() {\n" |
34 " throw new Exception(\"bad news\");\n" | 33 " throw new Exception(\"bad news\");\n" |
35 "}\n"; | 34 "}\n"; |
36 | 35 |
(...skipping 5442 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5479 ASSERT(function_name != NULL); | 5478 ASSERT(function_name != NULL); |
5480 if (!strcmp(function_name, "NativeArgument_Create")) { | 5479 if (!strcmp(function_name, "NativeArgument_Create")) { |
5481 return reinterpret_cast<Dart_NativeFunction>(&NativeArgumentCreate); | 5480 return reinterpret_cast<Dart_NativeFunction>(&NativeArgumentCreate); |
5482 } else if (!strcmp(function_name, "NativeArgument_Access")) { | 5481 } else if (!strcmp(function_name, "NativeArgument_Access")) { |
5483 return reinterpret_cast<Dart_NativeFunction>(&NativeArgumentAccess); | 5482 return reinterpret_cast<Dart_NativeFunction>(&NativeArgumentAccess); |
5484 } | 5483 } |
5485 return NULL; | 5484 return NULL; |
5486 } | 5485 } |
5487 | 5486 |
5488 TEST_CASE(DartAPI_GetNativeArguments) { | 5487 TEST_CASE(DartAPI_GetNativeArguments) { |
5489 const bool saved_flag = FLAG_support_externalizable_strings; | |
5490 FLAG_support_externalizable_strings = true; | |
5491 | |
5492 const char* kScriptChars = | 5488 const char* kScriptChars = |
5493 "import 'dart:nativewrappers';" | 5489 "import 'dart:nativewrappers';" |
5494 "class MyObject extends NativeFieldWrapperClass2 {" | 5490 "class MyObject extends NativeFieldWrapperClass2 {" |
5495 " static MyObject createObject() native 'NativeArgument_Create';" | 5491 " static MyObject createObject() native 'NativeArgument_Create';" |
5496 " int accessFields(int arg1," | 5492 " int accessFields(int arg1," |
5497 " int arg2," | 5493 " int arg2," |
5498 " bool arg3," | 5494 " bool arg3," |
5499 " double arg4," | 5495 " double arg4," |
5500 " String arg5," | 5496 " String arg5," |
5501 " String arg6," | 5497 " String arg6," |
5502 " MyObject arg7) native 'NativeArgument_Access';" | 5498 " MyObject arg7) native 'NativeArgument_Access';" |
5503 "}" | 5499 "}" |
5504 "int testMain(String extstr) {" | 5500 "int testMain(String extstr) {" |
5505 " String str = 'abcdefg';" | 5501 " String str = 'abcdefg';" |
5506 " MyObject obj1 = MyObject.createObject();" | 5502 " MyObject obj1 = MyObject.createObject();" |
5507 " MyObject obj2 = MyObject.createObject();" | 5503 " MyObject obj2 = MyObject.createObject();" |
5508 " return obj1.accessFields(77," | 5504 " return obj1.accessFields(77," |
5509 " 1 << 63," | 5505 " 1 << 63," |
5510 " true," | 5506 " true," |
5511 " 3.14," | 5507 " 3.14," |
5512 " str," | 5508 " str," |
5513 " extstr," | 5509 " extstr," |
5514 " obj2);" | 5510 " obj2);" |
5515 "}"; | 5511 "}"; |
5516 | 5512 |
5517 Dart_Handle lib = TestCase::LoadTestScript( | 5513 Dart_Handle lib = TestCase::LoadTestScript( |
5518 kScriptChars, | 5514 kScriptChars, |
5519 reinterpret_cast<Dart_NativeEntryResolver>(native_args_lookup)); | 5515 reinterpret_cast<Dart_NativeEntryResolver>(native_args_lookup)); |
5520 | 5516 |
5521 intptr_t size; | 5517 const char* ascii_str = "string"; |
5522 Dart_Handle ascii_str = NewString("string"); | 5518 Dart_Handle extstr = Dart_NewExternalLatin1String( |
5523 EXPECT_VALID(ascii_str); | 5519 reinterpret_cast<const uint8_t*>(ascii_str), strlen(ascii_str), |
5524 EXPECT_VALID(Dart_StringStorageSize(ascii_str, &size)); | |
5525 uint8_t ext_ascii_str[10]; | |
5526 Dart_Handle extstr = Dart_MakeExternalString( | |
5527 ascii_str, ext_ascii_str, size, | |
5528 reinterpret_cast<void*>(&native_arg_str_peer), NULL); | 5520 reinterpret_cast<void*>(&native_arg_str_peer), NULL); |
5529 | 5521 |
5530 Dart_Handle args[1]; | 5522 Dart_Handle args[1]; |
5531 args[0] = extstr; | 5523 args[0] = extstr; |
5532 Dart_Handle result = Dart_Invoke(lib, NewString("testMain"), 1, args); | 5524 Dart_Handle result = Dart_Invoke(lib, NewString("testMain"), 1, args); |
5533 EXPECT_VALID(result); | 5525 EXPECT_VALID(result); |
5534 EXPECT(Dart_IsInteger(result)); | 5526 EXPECT(Dart_IsInteger(result)); |
5535 | |
5536 FLAG_support_externalizable_strings = saved_flag; | |
5537 } | 5527 } |
5538 | 5528 |
5539 static void NativeArgumentCounter(Dart_NativeArguments args) { | 5529 static void NativeArgumentCounter(Dart_NativeArguments args) { |
5540 Dart_EnterScope(); | 5530 Dart_EnterScope(); |
5541 int count = Dart_GetNativeArgumentCount(args); | 5531 int count = Dart_GetNativeArgumentCount(args); |
5542 Dart_SetReturnValue(args, Dart_NewInteger(count)); | 5532 Dart_SetReturnValue(args, Dart_NewInteger(count)); |
5543 Dart_ExitScope(); | 5533 Dart_ExitScope(); |
5544 } | 5534 } |
5545 | 5535 |
5546 static Dart_NativeFunction gnac_lookup(Dart_Handle name, | 5536 static Dart_NativeFunction gnac_lookup(Dart_Handle name, |
(...skipping 2760 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8307 EXPECT(o2 == reinterpret_cast<void*>(&p2)); | 8297 EXPECT(o2 == reinterpret_cast<void*>(&p2)); |
8308 } | 8298 } |
8309 Dart_ExitScope(); | 8299 Dart_ExitScope(); |
8310 { | 8300 { |
8311 TransitionNativeToVM transition(thread); | 8301 TransitionNativeToVM transition(thread); |
8312 isolate->heap()->CollectGarbage(Heap::kOld); | 8302 isolate->heap()->CollectGarbage(Heap::kOld); |
8313 EXPECT_EQ(0, isolate->heap()->PeerCount()); | 8303 EXPECT_EQ(0, isolate->heap()->PeerCount()); |
8314 } | 8304 } |
8315 } | 8305 } |
8316 | 8306 |
8317 // Test API call to make strings external. | |
8318 static void MakeExternalCback(void* peer) { | |
8319 *static_cast<int*>(peer) *= 2; | |
8320 } | |
8321 | |
8322 TEST_CASE(DartAPI_MakeExternalString) { | |
8323 const bool saved_flag = FLAG_support_externalizable_strings; | |
8324 FLAG_support_externalizable_strings = true; | |
8325 | |
8326 static int peer8 = 40; | |
8327 static int peer16 = 41; | |
8328 static int canonical_str_peer = 42; | |
8329 intptr_t length = 0; | |
8330 intptr_t expected_length = 0; | |
8331 { | |
8332 Dart_EnterScope(); | |
8333 | |
8334 // First test some negative conditions. | |
8335 uint8_t data8[] = {'h', 'e', 'l', 'l', 'o'}; | |
8336 const char* err = "string"; | |
8337 Dart_Handle err_str = NewString(err); | |
8338 Dart_Handle ext_err_str = | |
8339 Dart_NewExternalLatin1String(data8, ARRAY_SIZE(data8), NULL, NULL); | |
8340 Dart_Handle result = Dart_MakeExternalString(Dart_Null(), data8, | |
8341 ARRAY_SIZE(data8), NULL, NULL); | |
8342 EXPECT(Dart_IsError(result)); // Null string object passed in. | |
8343 result = | |
8344 Dart_MakeExternalString(err_str, NULL, ARRAY_SIZE(data8), NULL, NULL); | |
8345 EXPECT(Dart_IsError(result)); // Null array pointer passed in. | |
8346 result = Dart_MakeExternalString(err_str, data8, 1, NULL, NULL); | |
8347 EXPECT(Dart_IsError(result)); // Invalid length passed in. | |
8348 | |
8349 const intptr_t kLength = 10; | |
8350 intptr_t size = 0; | |
8351 | |
8352 // Test with an external string. | |
8353 result = Dart_MakeExternalString(ext_err_str, data8, ARRAY_SIZE(data8), | |
8354 NULL, NULL); | |
8355 EXPECT(Dart_IsString(result)); | |
8356 EXPECT(Dart_IsExternalString(result)); | |
8357 | |
8358 // Test with an empty string. | |
8359 Dart_Handle empty_str = NewString(""); | |
8360 EXPECT(Dart_IsString(empty_str)); | |
8361 EXPECT(!Dart_IsExternalString(empty_str)); | |
8362 uint8_t ext_empty_str[kLength]; | |
8363 Dart_Handle str = | |
8364 Dart_MakeExternalString(empty_str, ext_empty_str, kLength, NULL, NULL); | |
8365 EXPECT(Dart_IsString(str)); | |
8366 EXPECT(Dart_IsString(empty_str)); | |
8367 EXPECT(Dart_IsStringLatin1(str)); | |
8368 EXPECT(Dart_IsStringLatin1(empty_str)); | |
8369 EXPECT(Dart_IsExternalString(str)); | |
8370 EXPECT(Dart_IsExternalString(empty_str)); | |
8371 EXPECT_VALID(Dart_StringLength(str, &length)); | |
8372 EXPECT_EQ(0, length); | |
8373 | |
8374 // Test with single character canonical string, it should not become | |
8375 // external string but the peer should be setup for it. | |
8376 Dart_Handle canonical_str = | |
8377 Api::NewHandle(thread, Symbols::New(thread, "*")); | |
8378 EXPECT(Dart_IsString(canonical_str)); | |
8379 EXPECT(!Dart_IsExternalString(canonical_str)); | |
8380 uint8_t ext_canonical_str[kLength]; | |
8381 str = Dart_MakeExternalString(canonical_str, ext_canonical_str, kLength, | |
8382 &canonical_str_peer, MakeExternalCback); | |
8383 EXPECT(Dart_IsString(str)); | |
8384 EXPECT(!Dart_IsExternalString(canonical_str)); | |
8385 EXPECT_EQ(canonical_str, str); | |
8386 EXPECT(Dart_IsString(canonical_str)); | |
8387 EXPECT(!Dart_IsExternalString(canonical_str)); | |
8388 void* peer; | |
8389 EXPECT_VALID(Dart_StringGetProperties(str, &size, &length, &peer)); | |
8390 EXPECT_EQ(1, size); | |
8391 EXPECT_EQ(1, length); | |
8392 EXPECT_EQ(reinterpret_cast<void*>(&canonical_str_peer), peer); | |
8393 | |
8394 // Test with a one byte ascii string. | |
8395 const char* ascii = "?unseen"; | |
8396 expected_length = strlen(ascii); | |
8397 Dart_Handle ascii_str = NewString(ascii); | |
8398 EXPECT_VALID(ascii_str); | |
8399 EXPECT(Dart_IsString(ascii_str)); | |
8400 EXPECT(Dart_IsStringLatin1(ascii_str)); | |
8401 EXPECT(!Dart_IsExternalString(ascii_str)); | |
8402 EXPECT_VALID(Dart_StringLength(ascii_str, &length)); | |
8403 EXPECT_EQ(expected_length, length); | |
8404 | |
8405 uint8_t ext_ascii_str[kLength]; | |
8406 EXPECT_VALID(Dart_StringStorageSize(ascii_str, &size)); | |
8407 str = Dart_MakeExternalString(ascii_str, ext_ascii_str, size, &peer8, | |
8408 MakeExternalCback); | |
8409 EXPECT(Dart_IsString(str)); | |
8410 EXPECT(Dart_IsString(ascii_str)); | |
8411 EXPECT(Dart_IsStringLatin1(str)); | |
8412 EXPECT(Dart_IsStringLatin1(ascii_str)); | |
8413 EXPECT(Dart_IsExternalString(str)); | |
8414 EXPECT(Dart_IsExternalString(ascii_str)); | |
8415 EXPECT_VALID(Dart_StringLength(str, &length)); | |
8416 EXPECT_EQ(expected_length, length); | |
8417 EXPECT_VALID(Dart_StringLength(ascii_str, &length)); | |
8418 EXPECT_EQ(expected_length, length); | |
8419 EXPECT(Dart_IdentityEquals(str, ascii_str)); | |
8420 for (intptr_t i = 0; i < length; i++) { | |
8421 EXPECT_EQ(ascii[i], ext_ascii_str[i]); | |
8422 } | |
8423 | |
8424 uint8_t data[] = {0xE4, 0xBA, 0x8c}; // U+4E8C. | |
8425 expected_length = 1; | |
8426 Dart_Handle utf16_str = Dart_NewStringFromUTF8(data, ARRAY_SIZE(data)); | |
8427 EXPECT_VALID(utf16_str); | |
8428 EXPECT(Dart_IsString(utf16_str)); | |
8429 EXPECT(!Dart_IsStringLatin1(utf16_str)); | |
8430 EXPECT(!Dart_IsExternalString(utf16_str)); | |
8431 EXPECT_VALID(Dart_StringLength(utf16_str, &length)); | |
8432 EXPECT_EQ(expected_length, length); | |
8433 | |
8434 // Test with a two byte string. | |
8435 uint16_t ext_utf16_str[kLength]; | |
8436 EXPECT_VALID(Dart_StringStorageSize(utf16_str, &size)); | |
8437 str = Dart_MakeExternalString(utf16_str, ext_utf16_str, size, &peer16, | |
8438 MakeExternalCback); | |
8439 EXPECT(Dart_IsString(str)); | |
8440 EXPECT(Dart_IsString(utf16_str)); | |
8441 EXPECT(!Dart_IsStringLatin1(str)); | |
8442 EXPECT(!Dart_IsStringLatin1(utf16_str)); | |
8443 EXPECT(Dart_IsExternalString(str)); | |
8444 EXPECT(Dart_IsExternalString(utf16_str)); | |
8445 EXPECT_VALID(Dart_StringLength(str, &length)); | |
8446 EXPECT_EQ(expected_length, length); | |
8447 EXPECT_VALID(Dart_StringLength(utf16_str, &length)); | |
8448 EXPECT_EQ(expected_length, length); | |
8449 EXPECT(Dart_IdentityEquals(str, utf16_str)); | |
8450 for (intptr_t i = 0; i < length; i++) { | |
8451 EXPECT_EQ(0x4e8c, ext_utf16_str[i]); | |
8452 } | |
8453 | |
8454 Zone* zone = thread->zone(); | |
8455 // Test with a symbol (hash value should be preserved on externalization). | |
8456 const char* symbol_ascii = "?unseen"; | |
8457 expected_length = strlen(symbol_ascii); | |
8458 Dart_Handle symbol_str = Api::NewHandle( | |
8459 thread, Symbols::New(thread, symbol_ascii, expected_length)); | |
8460 EXPECT_VALID(symbol_str); | |
8461 EXPECT(Dart_IsString(symbol_str)); | |
8462 EXPECT(Dart_IsStringLatin1(symbol_str)); | |
8463 EXPECT(!Dart_IsExternalString(symbol_str)); | |
8464 EXPECT_VALID(Dart_StringLength(symbol_str, &length)); | |
8465 EXPECT_EQ(expected_length, length); | |
8466 EXPECT(Api::UnwrapStringHandle(zone, symbol_str).HasHash()); | |
8467 | |
8468 uint8_t ext_symbol_ascii[kLength]; | |
8469 EXPECT_VALID(Dart_StringStorageSize(symbol_str, &size)); | |
8470 str = Dart_MakeExternalString(symbol_str, ext_symbol_ascii, size, &peer8, | |
8471 MakeExternalCback); | |
8472 EXPECT(Api::UnwrapStringHandle(zone, str).HasHash()); | |
8473 EXPECT(Api::UnwrapStringHandle(zone, str).Hash() == | |
8474 Api::UnwrapStringHandle(zone, symbol_str).Hash()); | |
8475 EXPECT(Dart_IsString(str)); | |
8476 EXPECT(Dart_IsString(symbol_str)); | |
8477 EXPECT(Dart_IsStringLatin1(str)); | |
8478 EXPECT(Dart_IsStringLatin1(symbol_str)); | |
8479 EXPECT(Dart_IsExternalString(str)); | |
8480 EXPECT(Dart_IsExternalString(symbol_str)); | |
8481 EXPECT_VALID(Dart_StringLength(str, &length)); | |
8482 EXPECT_EQ(expected_length, length); | |
8483 EXPECT_VALID(Dart_StringLength(symbol_str, &length)); | |
8484 EXPECT_EQ(expected_length, length); | |
8485 EXPECT(Dart_IdentityEquals(str, symbol_str)); | |
8486 for (intptr_t i = 0; i < length; i++) { | |
8487 EXPECT_EQ(symbol_ascii[i], ext_symbol_ascii[i]); | |
8488 } | |
8489 | |
8490 Dart_ExitScope(); | |
8491 } | |
8492 EXPECT_EQ(40, peer8); | |
8493 EXPECT_EQ(41, peer16); | |
8494 EXPECT_EQ(42, canonical_str_peer); | |
8495 { | |
8496 TransitionNativeToVM transition(thread); | |
8497 Isolate::Current()->heap()->CollectAllGarbage(); | |
8498 GCTestHelper::WaitForGCTasks(); | |
8499 } | |
8500 EXPECT_EQ(80, peer8); | |
8501 EXPECT_EQ(82, peer16); | |
8502 EXPECT_EQ(42, canonical_str_peer); // "*" Symbol is not removed on GC. | |
8503 | |
8504 FLAG_support_externalizable_strings = saved_flag; | |
8505 } | |
8506 | |
8507 TEST_CASE(DartAPI_ExternalizeConstantStrings) { | |
8508 const bool saved_flag = FLAG_support_externalizable_strings; | |
8509 FLAG_support_externalizable_strings = true; | |
8510 | |
8511 const char* kScriptChars = | |
8512 "String testMain() {\n" | |
8513 " return 'constant string';\n" | |
8514 "}\n"; | |
8515 | |
8516 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL); | |
8517 Dart_Handle result = Dart_Invoke(lib, NewString("testMain"), 0, NULL); | |
8518 const char* expected_str = "constant string"; | |
8519 const intptr_t kExpectedLen = 15; | |
8520 uint8_t ext_str[kExpectedLen]; | |
8521 Dart_Handle str = | |
8522 Dart_MakeExternalString(result, ext_str, kExpectedLen, NULL, NULL); | |
8523 | |
8524 EXPECT(Dart_IsExternalString(str)); | |
8525 for (intptr_t i = 0; i < kExpectedLen; i++) { | |
8526 EXPECT_EQ(expected_str[i], ext_str[i]); | |
8527 } | |
8528 | |
8529 FLAG_support_externalizable_strings = saved_flag; | |
8530 } | |
8531 | |
8532 TEST_CASE(DartAPI_LazyLoadDeoptimizes) { | 8307 TEST_CASE(DartAPI_LazyLoadDeoptimizes) { |
8533 const char* kLoadFirst = | 8308 const char* kLoadFirst = |
8534 "library L;\n" | 8309 "library L;\n" |
8535 "start(a) {\n" | 8310 "start(a) {\n" |
8536 " var obj = (a == 1) ? createB() : new A();\n" | 8311 " var obj = (a == 1) ? createB() : new A();\n" |
8537 " for (int i = 0; i < 4000; i++) {\n" | 8312 " for (int i = 0; i < 4000; i++) {\n" |
8538 " var res = obj.foo();\n" | 8313 " var res = obj.foo();\n" |
8539 " if (a == 1) { if (res != 1) throw 'Error'; }\n" | 8314 " if (a == 1) { if (res != 1) throw 'Error'; }\n" |
8540 " else if (res != 2) throw 'Error'; \n" | 8315 " else if (res != 2) throw 'Error'; \n" |
8541 " }\n" | 8316 " }\n" |
(...skipping 22 matching lines...) Expand all Loading... |
8564 Dart_Handle url = NewString(TestCase::url()); | 8339 Dart_Handle url = NewString(TestCase::url()); |
8565 Dart_LoadSource(TestCase::lib(), url, Dart_Null(), source, 0, 0); | 8340 Dart_LoadSource(TestCase::lib(), url, Dart_Null(), source, 0, 0); |
8566 result = Dart_FinalizeLoading(false); | 8341 result = Dart_FinalizeLoading(false); |
8567 EXPECT_VALID(result); | 8342 EXPECT_VALID(result); |
8568 | 8343 |
8569 dart_args[0] = Dart_NewInteger(1); | 8344 dart_args[0] = Dart_NewInteger(1); |
8570 result = Dart_Invoke(lib1, NewString("start"), 1, dart_args); | 8345 result = Dart_Invoke(lib1, NewString("start"), 1, dart_args); |
8571 EXPECT_VALID(result); | 8346 EXPECT_VALID(result); |
8572 } | 8347 } |
8573 | 8348 |
8574 // Test external strings and optimized code. | |
8575 static void ExternalStringDeoptimize_Finalize(void* peer) { | |
8576 delete[] reinterpret_cast<char*>(peer); | |
8577 } | |
8578 | |
8579 static void A_change_str_native(Dart_NativeArguments args) { | |
8580 Dart_EnterScope(); | |
8581 Dart_Handle str = Dart_GetNativeArgument(args, 0); | |
8582 EXPECT(Dart_IsString(str)); | |
8583 void* peer; | |
8584 Dart_Handle str_arg = Dart_GetNativeStringArgument(args, 0, &peer); | |
8585 EXPECT(Dart_IsString(str_arg)); | |
8586 EXPECT(!peer); | |
8587 intptr_t size = 0; | |
8588 EXPECT_VALID(Dart_StringStorageSize(str, &size)); | |
8589 intptr_t arg_size = 0; | |
8590 EXPECT_VALID(Dart_StringStorageSize(str_arg, &arg_size)); | |
8591 EXPECT_EQ(size, arg_size); | |
8592 char* str_data = new char[size]; | |
8593 Dart_Handle result = Dart_MakeExternalString( | |
8594 str, str_data, size, str_data, &ExternalStringDeoptimize_Finalize); | |
8595 EXPECT_VALID(result); | |
8596 EXPECT(Dart_IsExternalString(result)); | |
8597 Dart_ExitScope(); | |
8598 } | |
8599 | |
8600 static Dart_NativeFunction ExternalStringDeoptimize_native_lookup( | |
8601 Dart_Handle name, | |
8602 int argument_count, | |
8603 bool* auto_setup_scope) { | |
8604 ASSERT(auto_setup_scope != NULL); | |
8605 *auto_setup_scope = true; | |
8606 return reinterpret_cast<Dart_NativeFunction>(&A_change_str_native); | |
8607 } | |
8608 | |
8609 // Do not use guarding mechanism on externalizable classes, since their class | |
8610 // can change on the fly, | |
8611 TEST_CASE(DartAPI_GuardExternalizedString) { | |
8612 const bool saved_flag = FLAG_support_externalizable_strings; | |
8613 FLAG_support_externalizable_strings = true; | |
8614 | |
8615 const char* kScriptChars = | |
8616 "main() {\n" | |
8617 " var a = new A('hello');\n" | |
8618 " var res = runOne(a);\n" | |
8619 " if (res != 10640000) return -1;\n" | |
8620 " change_str(a.f);\n" | |
8621 " res = runOne(a);\n" | |
8622 " return res;\n" | |
8623 "}\n" | |
8624 "runOne(a) {\n" | |
8625 " var sum = 0;\n" | |
8626 " for (int i = 0; i < 20000; i++) {\n" | |
8627 " for (int j = 0; j < a.f.length; j++) {\n" | |
8628 " sum += a.f.codeUnitAt(j);\n" | |
8629 " }\n" | |
8630 " }\n" | |
8631 " return sum;\n" | |
8632 "}\n" | |
8633 "class A {\n" | |
8634 " var f;\n" | |
8635 " A(this.f);\n" | |
8636 "}\n" | |
8637 "change_str(String s) native 'A_change_str';\n" | |
8638 ""; | |
8639 Dart_Handle lib = TestCase::LoadTestScript( | |
8640 kScriptChars, &ExternalStringDeoptimize_native_lookup); | |
8641 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL); | |
8642 int64_t value = 0; | |
8643 result = Dart_IntegerToInt64(result, &value); | |
8644 EXPECT_VALID(result); | |
8645 EXPECT_EQ(10640000, value); | |
8646 | |
8647 FLAG_support_externalizable_strings = saved_flag; | |
8648 } | |
8649 | |
8650 TEST_CASE(DartAPI_ExternalStringDeoptimize) { | |
8651 const bool saved_flag = FLAG_support_externalizable_strings; | |
8652 FLAG_support_externalizable_strings = true; | |
8653 | |
8654 const char* kScriptChars = | |
8655 "String str = 'A';\n" | |
8656 "class A {\n" | |
8657 " static change_str(String s) native 'A_change_str';\n" | |
8658 "}\n" | |
8659 "sum_chars(String s, bool b) {\n" | |
8660 " var result = 0;\n" | |
8661 " for (var i = 0; i < s.length; i++) {\n" | |
8662 " if (b && i == 0) A.change_str(str);\n" | |
8663 " result += s.codeUnitAt(i);" | |
8664 " }\n" | |
8665 " return result;\n" | |
8666 "}\n" | |
8667 "main() {\n" | |
8668 " str = '$str$str';\n" | |
8669 " for (var i = 0; i < 2000; i++) sum_chars(str, false);\n" | |
8670 " var x = sum_chars(str, false);\n" | |
8671 " var y = sum_chars(str, true);\n" | |
8672 " return x + y;\n" | |
8673 "}\n"; | |
8674 Dart_Handle lib = TestCase::LoadTestScript( | |
8675 kScriptChars, &ExternalStringDeoptimize_native_lookup); | |
8676 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL); | |
8677 int64_t value = 0; | |
8678 result = Dart_IntegerToInt64(result, &value); | |
8679 EXPECT_VALID(result); | |
8680 EXPECT_EQ(260, value); | |
8681 | |
8682 FLAG_support_externalizable_strings = saved_flag; | |
8683 } | |
8684 | |
8685 TEST_CASE(DartAPI_ExternalStringPolymorphicDeoptimize) { | |
8686 const bool saved_flag = FLAG_support_externalizable_strings; | |
8687 FLAG_support_externalizable_strings = true; | |
8688 | |
8689 const char* kScriptChars = | |
8690 "const strA = 'AAAA';\n" | |
8691 "class A {\n" | |
8692 " static change_str(String s) native 'A_change_str';\n" | |
8693 "}\n" | |
8694 "compare(a, b, [i = 0]) {\n" | |
8695 " return a.codeUnitAt(i) == b.codeUnitAt(i);\n" | |
8696 "}\n" | |
8697 "compareA(b, [i = 0]) {\n" | |
8698 " return compare(strA, b, i);\n" | |
8699 "}\n" | |
8700 "main() {\n" | |
8701 " var externalA = 'AA' + 'AA';\n" | |
8702 " A.change_str(externalA);\n" | |
8703 " compare('AA' + 'AA', strA);\n" | |
8704 " compare(externalA, strA);\n" | |
8705 " for (var i = 0; i < 10000; i++) compareA(strA);\n" | |
8706 " A.change_str(strA);\n" | |
8707 " return compareA('AA' + 'AA');\n" | |
8708 "}\n"; | |
8709 Dart_Handle lib = TestCase::LoadTestScript( | |
8710 kScriptChars, &ExternalStringDeoptimize_native_lookup); | |
8711 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL); | |
8712 EXPECT_VALID(result); | |
8713 bool value = false; | |
8714 result = Dart_BooleanValue(result, &value); | |
8715 EXPECT_VALID(result); | |
8716 EXPECT(value); | |
8717 | |
8718 FLAG_support_externalizable_strings = saved_flag; | |
8719 } | |
8720 | |
8721 TEST_CASE(DartAPI_ExternalStringLoadElimination) { | |
8722 const bool saved_flag = FLAG_support_externalizable_strings; | |
8723 FLAG_support_externalizable_strings = true; | |
8724 | |
8725 const char* kScriptChars = | |
8726 "class A {\n" | |
8727 " static change_str(String s) native 'A_change_str';\n" | |
8728 "}\n" | |
8729 "double_char0(str) {\n" | |
8730 " return str.codeUnitAt(0) + str.codeUnitAt(0);\n" | |
8731 "}\n" | |
8732 "main() {\n" | |
8733 " var externalA = 'AA' + 'AA';\n" | |
8734 " A.change_str(externalA);\n" | |
8735 " for (var i = 0; i < 10000; i++) double_char0(externalA);\n" | |
8736 " var result = double_char0(externalA);\n" | |
8737 " return result == 130;\n" | |
8738 "}\n"; | |
8739 Dart_Handle lib = TestCase::LoadTestScript( | |
8740 kScriptChars, &ExternalStringDeoptimize_native_lookup); | |
8741 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL); | |
8742 EXPECT_VALID(result); | |
8743 bool value = false; | |
8744 result = Dart_BooleanValue(result, &value); | |
8745 EXPECT_VALID(result); | |
8746 EXPECT(value); | |
8747 | |
8748 FLAG_support_externalizable_strings = saved_flag; | |
8749 } | |
8750 | |
8751 TEST_CASE(DartAPI_ExternalStringGuardFieldDeoptimize) { | |
8752 const bool saved_flag = FLAG_support_externalizable_strings; | |
8753 FLAG_support_externalizable_strings = true; | |
8754 | |
8755 const char* kScriptChars = | |
8756 "const strA = 'AAAA';\n" | |
8757 "class A {\n" | |
8758 " static change_str(String s) native 'A_change_str';\n" | |
8759 "}\n" | |
8760 "class G { var f = 'A'; }\n" | |
8761 "final guard = new G();\n" | |
8762 "var shouldExternalize = false;\n" | |
8763 "ext() { if (shouldExternalize) A.change_str(strA); }\n" | |
8764 "compare(a, b, [i = 0]) {\n" | |
8765 " guard.f = a;\n" | |
8766 " ext();" | |
8767 " return a.codeUnitAt(i) == b.codeUnitAt(i);\n" | |
8768 "}\n" | |
8769 "compareA(b, [i = 0]) {\n" | |
8770 " return compare(strA, b, i);\n" | |
8771 "}\n" | |
8772 "main() {\n" | |
8773 " var externalA = 'AA' + 'AA';\n" | |
8774 " A.change_str(externalA);\n" | |
8775 " compare('AA' + 'AA', strA);\n" | |
8776 " for (var i = 0; i < 10000; i++) compareA(strA);\n" | |
8777 " shouldExternalize = true;\n" | |
8778 " return compareA('AA' + 'AA');\n" | |
8779 "}\n"; | |
8780 Dart_Handle lib = TestCase::LoadTestScript( | |
8781 kScriptChars, &ExternalStringDeoptimize_native_lookup); | |
8782 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL); | |
8783 EXPECT_VALID(result); | |
8784 bool value = false; | |
8785 result = Dart_BooleanValue(result, &value); | |
8786 EXPECT_VALID(result); | |
8787 EXPECT(value); | |
8788 | |
8789 FLAG_support_externalizable_strings = saved_flag; | |
8790 } | |
8791 | |
8792 TEST_CASE(DartAPI_ExternalStringStaticFieldDeoptimize) { | |
8793 const bool saved_flag = FLAG_support_externalizable_strings; | |
8794 FLAG_support_externalizable_strings = true; | |
8795 | |
8796 const char* kScriptChars = | |
8797 "const strA = 'AAAA';\n" | |
8798 "class A {\n" | |
8799 " static change_str(String s) native 'A_change_str';\n" | |
8800 "}\n" | |
8801 "class G { static final f = strA; }\n" | |
8802 "compare(a, b, [i = 0]) {\n" | |
8803 " return a.codeUnitAt(i) == b.codeUnitAt(i);\n" | |
8804 "}\n" | |
8805 "compareA(b, [i = 0]) {\n" | |
8806 " return compare(G.f, b, i);\n" | |
8807 "}\n" | |
8808 "main() {\n" | |
8809 " var externalA = 'AA' + 'AA';\n" | |
8810 " A.change_str(externalA);\n" | |
8811 " compare('AA' + 'AA', strA);\n" | |
8812 " for (var i = 0; i < 10000; i++) compareA(strA);\n" | |
8813 " A.change_str(G.f);" | |
8814 " return compareA('AA' + 'AA');\n" | |
8815 "}\n"; | |
8816 Dart_Handle lib = TestCase::LoadTestScript( | |
8817 kScriptChars, &ExternalStringDeoptimize_native_lookup); | |
8818 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL); | |
8819 EXPECT_VALID(result); | |
8820 bool value = false; | |
8821 result = Dart_BooleanValue(result, &value); | |
8822 EXPECT_VALID(result); | |
8823 EXPECT(value); | |
8824 | |
8825 FLAG_support_externalizable_strings = saved_flag; | |
8826 } | |
8827 | |
8828 TEST_CASE(DartAPI_ExternalStringTrimDoubleParse) { | |
8829 const bool saved_flag = FLAG_support_externalizable_strings; | |
8830 FLAG_support_externalizable_strings = true; | |
8831 | |
8832 const char* kScriptChars = | |
8833 "String str = 'A';\n" | |
8834 "class A {\n" | |
8835 " static change_str(String s) native 'A_change_str';\n" | |
8836 "}\n" | |
8837 "main() {\n" | |
8838 " var externalOneByteString = ' 0.2\\xA0 ';\n;" | |
8839 " A.change_str(externalOneByteString);\n" | |
8840 " var externalTwoByteString = ' \\u{2029}0.6\\u{2029} ';\n" | |
8841 " A.change_str(externalTwoByteString);\n" | |
8842 " var x = double.parse(externalOneByteString);\n" | |
8843 " var y = double.parse(externalTwoByteString);\n" | |
8844 " return ((x + y) * 10).toInt();\n" | |
8845 "}\n"; | |
8846 Dart_Handle lib = TestCase::LoadTestScript( | |
8847 kScriptChars, &ExternalStringDeoptimize_native_lookup); | |
8848 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL); | |
8849 int64_t value = 0; | |
8850 result = Dart_IntegerToInt64(result, &value); | |
8851 EXPECT_VALID(result); | |
8852 EXPECT_EQ(8, value); | |
8853 | |
8854 FLAG_support_externalizable_strings = saved_flag; | |
8855 } | |
8856 | |
8857 TEST_CASE(DartAPI_ExternalStringDoubleParse) { | |
8858 const bool saved_flag = FLAG_support_externalizable_strings; | |
8859 FLAG_support_externalizable_strings = true; | |
8860 | |
8861 const char* kScriptChars = | |
8862 "String str = 'A';\n" | |
8863 "class A {\n" | |
8864 " static change_str(String s) native 'A_change_str';\n" | |
8865 "}\n" | |
8866 "main() {\n" | |
8867 " var externalOneByteString = '0.2';\n;" | |
8868 " A.change_str(externalOneByteString);\n" | |
8869 " var externalTwoByteString = '0.6';\n" | |
8870 " A.change_str(externalTwoByteString);\n" | |
8871 " var x = double.parse(externalOneByteString);\n" | |
8872 " var y = double.parse(externalTwoByteString);\n" | |
8873 " return ((x + y) * 10).toInt();\n" | |
8874 "}\n"; | |
8875 Dart_Handle lib = TestCase::LoadTestScript( | |
8876 kScriptChars, &ExternalStringDeoptimize_native_lookup); | |
8877 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL); | |
8878 int64_t value = 0; | |
8879 result = Dart_IntegerToInt64(result, &value); | |
8880 EXPECT_VALID(result); | |
8881 EXPECT_EQ(8, value); | |
8882 | |
8883 FLAG_support_externalizable_strings = saved_flag; | |
8884 } | |
8885 | |
8886 TEST_CASE(DartAPI_ExternalStringIndexOf) { | 8349 TEST_CASE(DartAPI_ExternalStringIndexOf) { |
8887 const char* kScriptChars = | 8350 const char* kScriptChars = |
8888 "main(String pattern) {\n" | 8351 "main(String pattern) {\n" |
8889 " var str = 'Hello World';\n" | 8352 " var str = 'Hello World';\n" |
8890 " return str.indexOf(pattern);\n" | 8353 " return str.indexOf(pattern);\n" |
8891 "}\n"; | 8354 "}\n"; |
8892 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL); | 8355 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL); |
8893 | 8356 |
8894 uint8_t data8[] = {'W'}; | 8357 uint8_t data8[] = {'W'}; |
8895 Dart_Handle ext8 = | 8358 Dart_Handle ext8 = |
(...skipping 790 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9686 EXPECT_VALID(result); | 9149 EXPECT_VALID(result); |
9687 result = Dart_FinalizeLoading(false); | 9150 result = Dart_FinalizeLoading(false); |
9688 EXPECT_VALID(result); | 9151 EXPECT_VALID(result); |
9689 result = Dart_Invoke(lib, NewString("foozoo"), 0, NULL); | 9152 result = Dart_Invoke(lib, NewString("foozoo"), 0, NULL); |
9690 EXPECT(Dart_IsError(result)); | 9153 EXPECT(Dart_IsError(result)); |
9691 } | 9154 } |
9692 | 9155 |
9693 #endif // !PRODUCT | 9156 #endif // !PRODUCT |
9694 | 9157 |
9695 } // namespace dart | 9158 } // namespace dart |
OLD | NEW |