OLD | NEW |
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, 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/bootstrap_natives.h" | 5 #include "vm/bootstrap_natives.h" |
6 | 6 |
7 #include "include/dart_api.h" | 7 #include "include/dart_api.h" |
| 8 #include "vm/dart_api_impl.h" |
8 #include "vm/exceptions.h" | 9 #include "vm/exceptions.h" |
9 #include "vm/dart_api_impl.h" | |
10 #include "vm/isolate.h" | 10 #include "vm/isolate.h" |
11 #include "vm/native_entry.h" | 11 #include "vm/native_entry.h" |
12 #include "vm/object.h" | 12 #include "vm/object.h" |
13 #include "vm/symbols.h" | 13 #include "vm/symbols.h" |
14 #include "vm/unicode.h" | 14 #include "vm/unicode.h" |
15 | 15 |
16 namespace dart { | 16 namespace dart { |
17 | 17 |
18 DEFINE_NATIVE_ENTRY(String_fromEnvironment, 3) { | 18 DEFINE_NATIVE_ENTRY(String_fromEnvironment, 3) { |
19 GET_NON_NULL_NATIVE_ARGUMENT(String, name, arguments->NativeArgAt(1)); | 19 GET_NON_NULL_NATIVE_ARGUMENT(String, name, arguments->NativeArgAt(1)); |
20 GET_NATIVE_ARGUMENT(String, default_value, arguments->NativeArgAt(2)); | 20 GET_NATIVE_ARGUMENT(String, default_value, arguments->NativeArgAt(2)); |
21 // Call the embedder to supply us with the environment. | 21 // Call the embedder to supply us with the environment. |
22 const String& env_value = | 22 const String& env_value = |
23 String::Handle(Api::GetEnvironmentValue(thread, name)); | 23 String::Handle(Api::GetEnvironmentValue(thread, name)); |
24 if (!env_value.IsNull()) { | 24 if (!env_value.IsNull()) { |
25 return Symbols::New(thread, env_value); | 25 return Symbols::New(thread, env_value); |
26 } | 26 } |
27 return default_value.raw(); | 27 return default_value.raw(); |
28 } | 28 } |
29 | 29 |
30 | |
31 DEFINE_NATIVE_ENTRY(StringBase_createFromCodePoints, 3) { | 30 DEFINE_NATIVE_ENTRY(StringBase_createFromCodePoints, 3) { |
32 GET_NON_NULL_NATIVE_ARGUMENT(Instance, list, arguments->NativeArgAt(0)); | 31 GET_NON_NULL_NATIVE_ARGUMENT(Instance, list, arguments->NativeArgAt(0)); |
33 GET_NON_NULL_NATIVE_ARGUMENT(Smi, start_obj, arguments->NativeArgAt(1)); | 32 GET_NON_NULL_NATIVE_ARGUMENT(Smi, start_obj, arguments->NativeArgAt(1)); |
34 GET_NON_NULL_NATIVE_ARGUMENT(Smi, end_obj, arguments->NativeArgAt(2)); | 33 GET_NON_NULL_NATIVE_ARGUMENT(Smi, end_obj, arguments->NativeArgAt(2)); |
35 | 34 |
36 Array& a = Array::Handle(); | 35 Array& a = Array::Handle(); |
37 intptr_t length; | 36 intptr_t length; |
38 if (list.IsGrowableObjectArray()) { | 37 if (list.IsGrowableObjectArray()) { |
39 const GrowableObjectArray& growableArray = GrowableObjectArray::Cast(list); | 38 const GrowableObjectArray& growableArray = GrowableObjectArray::Cast(list); |
40 a ^= growableArray.data(); | 39 a ^= growableArray.data(); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
82 } | 81 } |
83 } | 82 } |
84 utf32_array[i] = value32; | 83 utf32_array[i] = value32; |
85 } | 84 } |
86 if (is_one_byte_string) { | 85 if (is_one_byte_string) { |
87 return OneByteString::New(utf32_array, array_len, Heap::kNew); | 86 return OneByteString::New(utf32_array, array_len, Heap::kNew); |
88 } | 87 } |
89 return TwoByteString::New(utf16_len, utf32_array, array_len, Heap::kNew); | 88 return TwoByteString::New(utf16_len, utf32_array, array_len, Heap::kNew); |
90 } | 89 } |
91 | 90 |
92 | |
93 DEFINE_NATIVE_ENTRY(StringBase_substringUnchecked, 3) { | 91 DEFINE_NATIVE_ENTRY(StringBase_substringUnchecked, 3) { |
94 const String& receiver = | 92 const String& receiver = |
95 String::CheckedHandle(zone, arguments->NativeArgAt(0)); | 93 String::CheckedHandle(zone, arguments->NativeArgAt(0)); |
96 GET_NON_NULL_NATIVE_ARGUMENT(Smi, start_obj, arguments->NativeArgAt(1)); | 94 GET_NON_NULL_NATIVE_ARGUMENT(Smi, start_obj, arguments->NativeArgAt(1)); |
97 GET_NON_NULL_NATIVE_ARGUMENT(Smi, end_obj, arguments->NativeArgAt(2)); | 95 GET_NON_NULL_NATIVE_ARGUMENT(Smi, end_obj, arguments->NativeArgAt(2)); |
98 | 96 |
99 intptr_t start = start_obj.Value(); | 97 intptr_t start = start_obj.Value(); |
100 intptr_t end = end_obj.Value(); | 98 intptr_t end = end_obj.Value(); |
101 return String::SubString(receiver, start, (end - start)); | 99 return String::SubString(receiver, start, (end - start)); |
102 } | 100 } |
103 | 101 |
104 | |
105 // Return the bitwise-or of all characters in the slice from start to end. | 102 // Return the bitwise-or of all characters in the slice from start to end. |
106 static uint16_t CharacterLimit(const String& string, | 103 static uint16_t CharacterLimit(const String& string, |
107 intptr_t start, | 104 intptr_t start, |
108 intptr_t end) { | 105 intptr_t end) { |
109 ASSERT(string.IsTwoByteString() || string.IsExternalTwoByteString()); | 106 ASSERT(string.IsTwoByteString() || string.IsExternalTwoByteString()); |
110 // Maybe do loop unrolling, and handle two uint16_t in a single uint32_t | 107 // Maybe do loop unrolling, and handle two uint16_t in a single uint32_t |
111 // operation. | 108 // operation. |
112 NoSafepointScope no_safepoint; | 109 NoSafepointScope no_safepoint; |
113 uint16_t result = 0; | 110 uint16_t result = 0; |
114 if (string.IsTwoByteString()) { | 111 if (string.IsTwoByteString()) { |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
155 } | 152 } |
156 uint16_t char_limit = CharacterLimit(base, slice_start, slice_end); | 153 uint16_t char_limit = CharacterLimit(base, slice_start, slice_end); |
157 if (char_limit > 0xff) { | 154 if (char_limit > 0xff) { |
158 return false; | 155 return false; |
159 } | 156 } |
160 } | 157 } |
161 } | 158 } |
162 return true; | 159 return true; |
163 } | 160 } |
164 | 161 |
165 | |
166 DEFINE_NATIVE_ENTRY(StringBase_joinReplaceAllResult, 4) { | 162 DEFINE_NATIVE_ENTRY(StringBase_joinReplaceAllResult, 4) { |
167 const String& base = String::CheckedHandle(zone, arguments->NativeArgAt(0)); | 163 const String& base = String::CheckedHandle(zone, arguments->NativeArgAt(0)); |
168 GET_NON_NULL_NATIVE_ARGUMENT(GrowableObjectArray, matches_growable, | 164 GET_NON_NULL_NATIVE_ARGUMENT(GrowableObjectArray, matches_growable, |
169 arguments->NativeArgAt(1)); | 165 arguments->NativeArgAt(1)); |
170 GET_NON_NULL_NATIVE_ARGUMENT(Smi, length_obj, arguments->NativeArgAt(2)); | 166 GET_NON_NULL_NATIVE_ARGUMENT(Smi, length_obj, arguments->NativeArgAt(2)); |
171 GET_NON_NULL_NATIVE_ARGUMENT(Bool, is_onebyte_obj, arguments->NativeArgAt(3)); | 167 GET_NON_NULL_NATIVE_ARGUMENT(Bool, is_onebyte_obj, arguments->NativeArgAt(3)); |
172 | 168 |
173 intptr_t len = matches_growable.Length(); | 169 intptr_t len = matches_growable.Length(); |
174 const Array& matches = Array::Handle(zone, matches_growable.data()); | 170 const Array& matches = Array::Handle(zone, matches_growable.data()); |
175 | 171 |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
253 String::CheckedHandle(zone, arguments->NativeArgAt(0)); | 249 String::CheckedHandle(zone, arguments->NativeArgAt(0)); |
254 ASSERT(receiver.IsOneByteString()); | 250 ASSERT(receiver.IsOneByteString()); |
255 GET_NON_NULL_NATIVE_ARGUMENT(Smi, start_obj, arguments->NativeArgAt(1)); | 251 GET_NON_NULL_NATIVE_ARGUMENT(Smi, start_obj, arguments->NativeArgAt(1)); |
256 GET_NON_NULL_NATIVE_ARGUMENT(Smi, end_obj, arguments->NativeArgAt(2)); | 252 GET_NON_NULL_NATIVE_ARGUMENT(Smi, end_obj, arguments->NativeArgAt(2)); |
257 | 253 |
258 const intptr_t start = start_obj.Value(); | 254 const intptr_t start = start_obj.Value(); |
259 const intptr_t end = end_obj.Value(); | 255 const intptr_t end = end_obj.Value(); |
260 return OneByteString::New(receiver, start, end - start, Heap::kNew); | 256 return OneByteString::New(receiver, start, end - start, Heap::kNew); |
261 } | 257 } |
262 | 258 |
263 | |
264 // This is high-performance code. | 259 // This is high-performance code. |
265 DEFINE_NATIVE_ENTRY(OneByteString_splitWithCharCode, 2) { | 260 DEFINE_NATIVE_ENTRY(OneByteString_splitWithCharCode, 2) { |
266 const String& receiver = | 261 const String& receiver = |
267 String::CheckedHandle(zone, arguments->NativeArgAt(0)); | 262 String::CheckedHandle(zone, arguments->NativeArgAt(0)); |
268 ASSERT(receiver.IsOneByteString()); | 263 ASSERT(receiver.IsOneByteString()); |
269 GET_NON_NULL_NATIVE_ARGUMENT(Smi, smi_split_code, arguments->NativeArgAt(1)); | 264 GET_NON_NULL_NATIVE_ARGUMENT(Smi, smi_split_code, arguments->NativeArgAt(1)); |
270 const intptr_t len = receiver.Length(); | 265 const intptr_t len = receiver.Length(); |
271 const intptr_t split_code = smi_split_code.Value(); | 266 const intptr_t split_code = smi_split_code.Value(); |
272 const GrowableObjectArray& result = GrowableObjectArray::Handle( | 267 const GrowableObjectArray& result = GrowableObjectArray::Handle( |
273 zone, GrowableObjectArray::New(16, Heap::kNew)); | 268 zone, GrowableObjectArray::New(16, Heap::kNew)); |
274 String& str = String::Handle(zone); | 269 String& str = String::Handle(zone); |
275 intptr_t start = 0; | 270 intptr_t start = 0; |
276 intptr_t i = 0; | 271 intptr_t i = 0; |
277 for (; i < len; i++) { | 272 for (; i < len; i++) { |
278 if (split_code == OneByteString::CharAt(receiver, i)) { | 273 if (split_code == OneByteString::CharAt(receiver, i)) { |
279 str = OneByteString::SubStringUnchecked(receiver, start, (i - start), | 274 str = OneByteString::SubStringUnchecked(receiver, start, (i - start), |
280 Heap::kNew); | 275 Heap::kNew); |
281 result.Add(str); | 276 result.Add(str); |
282 start = i + 1; | 277 start = i + 1; |
283 } | 278 } |
284 } | 279 } |
285 str = OneByteString::SubStringUnchecked(receiver, start, (i - start), | 280 str = OneByteString::SubStringUnchecked(receiver, start, (i - start), |
286 Heap::kNew); | 281 Heap::kNew); |
287 result.Add(str); | 282 result.Add(str); |
288 return result.raw(); | 283 return result.raw(); |
289 } | 284 } |
290 | 285 |
291 | |
292 DEFINE_NATIVE_ENTRY(OneByteString_allocate, 1) { | 286 DEFINE_NATIVE_ENTRY(OneByteString_allocate, 1) { |
293 GET_NON_NULL_NATIVE_ARGUMENT(Smi, length_obj, arguments->NativeArgAt(0)); | 287 GET_NON_NULL_NATIVE_ARGUMENT(Smi, length_obj, arguments->NativeArgAt(0)); |
294 return OneByteString::New(length_obj.Value(), Heap::kNew); | 288 return OneByteString::New(length_obj.Value(), Heap::kNew); |
295 } | 289 } |
296 | 290 |
297 | |
298 DEFINE_NATIVE_ENTRY(OneByteString_allocateFromOneByteList, 3) { | 291 DEFINE_NATIVE_ENTRY(OneByteString_allocateFromOneByteList, 3) { |
299 Instance& list = Instance::CheckedHandle(zone, arguments->NativeArgAt(0)); | 292 Instance& list = Instance::CheckedHandle(zone, arguments->NativeArgAt(0)); |
300 GET_NON_NULL_NATIVE_ARGUMENT(Smi, start_obj, arguments->NativeArgAt(1)); | 293 GET_NON_NULL_NATIVE_ARGUMENT(Smi, start_obj, arguments->NativeArgAt(1)); |
301 GET_NON_NULL_NATIVE_ARGUMENT(Smi, end_obj, arguments->NativeArgAt(2)); | 294 GET_NON_NULL_NATIVE_ARGUMENT(Smi, end_obj, arguments->NativeArgAt(2)); |
302 | 295 |
303 intptr_t start = start_obj.Value(); | 296 intptr_t start = start_obj.Value(); |
304 intptr_t end = end_obj.Value(); | 297 intptr_t end = end_obj.Value(); |
305 if (start < 0) { | 298 if (start < 0) { |
306 const Array& args = Array::Handle(Array::New(1)); | 299 const Array& args = Array::Handle(Array::New(1)); |
307 args.SetAt(0, start_obj); | 300 args.SetAt(0, start_obj); |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
374 intptr_t value = | 367 intptr_t value = |
375 Smi::Value(reinterpret_cast<RawSmi*>(array.At(start + i))); | 368 Smi::Value(reinterpret_cast<RawSmi*>(array.At(start + i))); |
376 OneByteString::SetCharAt(string, i, value); | 369 OneByteString::SetCharAt(string, i, value); |
377 } | 370 } |
378 return string.raw(); | 371 return string.raw(); |
379 } | 372 } |
380 UNREACHABLE(); | 373 UNREACHABLE(); |
381 return Object::null(); | 374 return Object::null(); |
382 } | 375 } |
383 | 376 |
384 | |
385 DEFINE_NATIVE_ENTRY(OneByteString_setAt, 3) { | 377 DEFINE_NATIVE_ENTRY(OneByteString_setAt, 3) { |
386 GET_NON_NULL_NATIVE_ARGUMENT(String, receiver, arguments->NativeArgAt(0)); | 378 GET_NON_NULL_NATIVE_ARGUMENT(String, receiver, arguments->NativeArgAt(0)); |
387 ASSERT(receiver.IsOneByteString()); | 379 ASSERT(receiver.IsOneByteString()); |
388 GET_NON_NULL_NATIVE_ARGUMENT(Smi, index_obj, arguments->NativeArgAt(1)); | 380 GET_NON_NULL_NATIVE_ARGUMENT(Smi, index_obj, arguments->NativeArgAt(1)); |
389 GET_NON_NULL_NATIVE_ARGUMENT(Smi, code_point_obj, arguments->NativeArgAt(2)); | 381 GET_NON_NULL_NATIVE_ARGUMENT(Smi, code_point_obj, arguments->NativeArgAt(2)); |
390 ASSERT((0 <= code_point_obj.Value()) && (code_point_obj.Value() <= 0xFF)); | 382 ASSERT((0 <= code_point_obj.Value()) && (code_point_obj.Value() <= 0xFF)); |
391 OneByteString::SetCharAt(receiver, index_obj.Value(), code_point_obj.Value()); | 383 OneByteString::SetCharAt(receiver, index_obj.Value(), code_point_obj.Value()); |
392 return Object::null(); | 384 return Object::null(); |
393 } | 385 } |
394 | 386 |
395 | |
396 DEFINE_NATIVE_ENTRY(ExternalOneByteString_getCid, 0) { | 387 DEFINE_NATIVE_ENTRY(ExternalOneByteString_getCid, 0) { |
397 return Smi::New(kExternalOneByteStringCid); | 388 return Smi::New(kExternalOneByteStringCid); |
398 } | 389 } |
399 | 390 |
400 | |
401 DEFINE_NATIVE_ENTRY(TwoByteString_allocateFromTwoByteList, 3) { | 391 DEFINE_NATIVE_ENTRY(TwoByteString_allocateFromTwoByteList, 3) { |
402 Instance& list = Instance::CheckedHandle(zone, arguments->NativeArgAt(0)); | 392 Instance& list = Instance::CheckedHandle(zone, arguments->NativeArgAt(0)); |
403 GET_NON_NULL_NATIVE_ARGUMENT(Smi, start_obj, arguments->NativeArgAt(1)); | 393 GET_NON_NULL_NATIVE_ARGUMENT(Smi, start_obj, arguments->NativeArgAt(1)); |
404 GET_NON_NULL_NATIVE_ARGUMENT(Smi, end_obj, arguments->NativeArgAt(2)); | 394 GET_NON_NULL_NATIVE_ARGUMENT(Smi, end_obj, arguments->NativeArgAt(2)); |
405 | 395 |
406 intptr_t start = start_obj.Value(); | 396 intptr_t start = start_obj.Value(); |
407 intptr_t end = end_obj.Value(); | 397 intptr_t end = end_obj.Value(); |
408 if (start < 0) { | 398 if (start < 0) { |
409 Exceptions::ThrowArgumentError(start_obj); | 399 Exceptions::ThrowArgumentError(start_obj); |
410 } | 400 } |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
476 intptr_t value = | 466 intptr_t value = |
477 Smi::Value(reinterpret_cast<RawSmi*>(array.At(start + i))); | 467 Smi::Value(reinterpret_cast<RawSmi*>(array.At(start + i))); |
478 TwoByteString::SetCharAt(string, i, value); | 468 TwoByteString::SetCharAt(string, i, value); |
479 } | 469 } |
480 return string.raw(); | 470 return string.raw(); |
481 } | 471 } |
482 UNREACHABLE(); | 472 UNREACHABLE(); |
483 return Object::null(); | 473 return Object::null(); |
484 } | 474 } |
485 | 475 |
486 | |
487 DEFINE_NATIVE_ENTRY(String_getHashCode, 1) { | 476 DEFINE_NATIVE_ENTRY(String_getHashCode, 1) { |
488 const String& receiver = | 477 const String& receiver = |
489 String::CheckedHandle(zone, arguments->NativeArgAt(0)); | 478 String::CheckedHandle(zone, arguments->NativeArgAt(0)); |
490 intptr_t hash_val = receiver.Hash(); | 479 intptr_t hash_val = receiver.Hash(); |
491 ASSERT(hash_val > 0); | 480 ASSERT(hash_val > 0); |
492 ASSERT(Smi::IsValid(hash_val)); | 481 ASSERT(Smi::IsValid(hash_val)); |
493 return Smi::New(hash_val); | 482 return Smi::New(hash_val); |
494 } | 483 } |
495 | 484 |
496 | |
497 DEFINE_NATIVE_ENTRY(String_getLength, 1) { | 485 DEFINE_NATIVE_ENTRY(String_getLength, 1) { |
498 const String& receiver = | 486 const String& receiver = |
499 String::CheckedHandle(zone, arguments->NativeArgAt(0)); | 487 String::CheckedHandle(zone, arguments->NativeArgAt(0)); |
500 return Smi::New(receiver.Length()); | 488 return Smi::New(receiver.Length()); |
501 } | 489 } |
502 | 490 |
503 | |
504 static uint16_t StringValueAt(const String& str, const Integer& index) { | 491 static uint16_t StringValueAt(const String& str, const Integer& index) { |
505 if (index.IsSmi()) { | 492 if (index.IsSmi()) { |
506 const intptr_t index_value = Smi::Cast(index).Value(); | 493 const intptr_t index_value = Smi::Cast(index).Value(); |
507 if ((0 <= index_value) && (index_value < str.Length())) { | 494 if ((0 <= index_value) && (index_value < str.Length())) { |
508 return str.CharAt(index_value); | 495 return str.CharAt(index_value); |
509 } | 496 } |
510 } | 497 } |
511 | 498 |
512 // An index larger than Smi is always illegal. | 499 // An index larger than Smi is always illegal. |
513 Exceptions::ThrowRangeError("index", index, 0, str.Length() - 1); | 500 Exceptions::ThrowRangeError("index", index, 0, str.Length() - 1); |
514 return 0; | 501 return 0; |
515 } | 502 } |
516 | 503 |
517 | |
518 DEFINE_NATIVE_ENTRY(String_charAt, 2) { | 504 DEFINE_NATIVE_ENTRY(String_charAt, 2) { |
519 const String& receiver = | 505 const String& receiver = |
520 String::CheckedHandle(zone, arguments->NativeArgAt(0)); | 506 String::CheckedHandle(zone, arguments->NativeArgAt(0)); |
521 GET_NON_NULL_NATIVE_ARGUMENT(Integer, index, arguments->NativeArgAt(1)); | 507 GET_NON_NULL_NATIVE_ARGUMENT(Integer, index, arguments->NativeArgAt(1)); |
522 uint16_t value = StringValueAt(receiver, index); | 508 uint16_t value = StringValueAt(receiver, index); |
523 return Symbols::FromCharCode(thread, static_cast<int32_t>(value)); | 509 return Symbols::FromCharCode(thread, static_cast<int32_t>(value)); |
524 } | 510 } |
525 | 511 |
526 | |
527 // Returns the 16-bit UTF-16 code unit at the given index. | 512 // Returns the 16-bit UTF-16 code unit at the given index. |
528 DEFINE_NATIVE_ENTRY(String_codeUnitAt, 2) { | 513 DEFINE_NATIVE_ENTRY(String_codeUnitAt, 2) { |
529 const String& receiver = | 514 const String& receiver = |
530 String::CheckedHandle(zone, arguments->NativeArgAt(0)); | 515 String::CheckedHandle(zone, arguments->NativeArgAt(0)); |
531 GET_NON_NULL_NATIVE_ARGUMENT(Integer, index, arguments->NativeArgAt(1)); | 516 GET_NON_NULL_NATIVE_ARGUMENT(Integer, index, arguments->NativeArgAt(1)); |
532 uint16_t value = StringValueAt(receiver, index); | 517 uint16_t value = StringValueAt(receiver, index); |
533 return Smi::New(static_cast<intptr_t>(value)); | 518 return Smi::New(static_cast<intptr_t>(value)); |
534 } | 519 } |
535 | 520 |
536 | |
537 DEFINE_NATIVE_ENTRY(String_concat, 2) { | 521 DEFINE_NATIVE_ENTRY(String_concat, 2) { |
538 const String& receiver = | 522 const String& receiver = |
539 String::CheckedHandle(zone, arguments->NativeArgAt(0)); | 523 String::CheckedHandle(zone, arguments->NativeArgAt(0)); |
540 GET_NON_NULL_NATIVE_ARGUMENT(String, b, arguments->NativeArgAt(1)); | 524 GET_NON_NULL_NATIVE_ARGUMENT(String, b, arguments->NativeArgAt(1)); |
541 return String::Concat(receiver, b); | 525 return String::Concat(receiver, b); |
542 } | 526 } |
543 | 527 |
544 | |
545 DEFINE_NATIVE_ENTRY(String_toLowerCase, 1) { | 528 DEFINE_NATIVE_ENTRY(String_toLowerCase, 1) { |
546 const String& receiver = | 529 const String& receiver = |
547 String::CheckedHandle(zone, arguments->NativeArgAt(0)); | 530 String::CheckedHandle(zone, arguments->NativeArgAt(0)); |
548 ASSERT(!receiver.IsNull()); | 531 ASSERT(!receiver.IsNull()); |
549 return String::ToLowerCase(receiver); | 532 return String::ToLowerCase(receiver); |
550 } | 533 } |
551 | 534 |
552 | |
553 DEFINE_NATIVE_ENTRY(String_toUpperCase, 1) { | 535 DEFINE_NATIVE_ENTRY(String_toUpperCase, 1) { |
554 const String& receiver = | 536 const String& receiver = |
555 String::CheckedHandle(zone, arguments->NativeArgAt(0)); | 537 String::CheckedHandle(zone, arguments->NativeArgAt(0)); |
556 ASSERT(!receiver.IsNull()); | 538 ASSERT(!receiver.IsNull()); |
557 return String::ToUpperCase(receiver); | 539 return String::ToUpperCase(receiver); |
558 } | 540 } |
559 | 541 |
560 | |
561 DEFINE_NATIVE_ENTRY(String_concatRange, 3) { | 542 DEFINE_NATIVE_ENTRY(String_concatRange, 3) { |
562 GET_NON_NULL_NATIVE_ARGUMENT(Instance, argument, arguments->NativeArgAt(0)); | 543 GET_NON_NULL_NATIVE_ARGUMENT(Instance, argument, arguments->NativeArgAt(0)); |
563 GET_NON_NULL_NATIVE_ARGUMENT(Smi, start, arguments->NativeArgAt(1)); | 544 GET_NON_NULL_NATIVE_ARGUMENT(Smi, start, arguments->NativeArgAt(1)); |
564 GET_NON_NULL_NATIVE_ARGUMENT(Smi, end, arguments->NativeArgAt(2)); | 545 GET_NON_NULL_NATIVE_ARGUMENT(Smi, end, arguments->NativeArgAt(2)); |
565 const intptr_t start_ix = start.Value(); | 546 const intptr_t start_ix = start.Value(); |
566 const intptr_t end_ix = end.Value(); | 547 const intptr_t end_ix = end.Value(); |
567 if (start_ix < 0) { | 548 if (start_ix < 0) { |
568 Exceptions::ThrowArgumentError(start); | 549 Exceptions::ThrowArgumentError(start); |
569 } | 550 } |
570 Array& strings = Array::Handle(); | 551 Array& strings = Array::Handle(); |
(...skipping 15 matching lines...) Expand all Loading... |
586 // Check that the array contains strings. | 567 // Check that the array contains strings. |
587 Instance& elem = Instance::Handle(); | 568 Instance& elem = Instance::Handle(); |
588 for (intptr_t i = start_ix; i < end_ix; i++) { | 569 for (intptr_t i = start_ix; i < end_ix; i++) { |
589 elem ^= strings.At(i); | 570 elem ^= strings.At(i); |
590 ASSERT(elem.IsString()); | 571 ASSERT(elem.IsString()); |
591 } | 572 } |
592 #endif | 573 #endif |
593 return String::ConcatAllRange(strings, start_ix, end_ix, Heap::kNew); | 574 return String::ConcatAllRange(strings, start_ix, end_ix, Heap::kNew); |
594 } | 575 } |
595 | 576 |
596 | |
597 DEFINE_NATIVE_ENTRY(StringBuffer_createStringFromUint16Array, 3) { | 577 DEFINE_NATIVE_ENTRY(StringBuffer_createStringFromUint16Array, 3) { |
598 GET_NON_NULL_NATIVE_ARGUMENT(TypedData, codeUnits, arguments->NativeArgAt(0)); | 578 GET_NON_NULL_NATIVE_ARGUMENT(TypedData, codeUnits, arguments->NativeArgAt(0)); |
599 GET_NON_NULL_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(1)); | 579 GET_NON_NULL_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(1)); |
600 GET_NON_NULL_NATIVE_ARGUMENT(Bool, isLatin1, arguments->NativeArgAt(2)); | 580 GET_NON_NULL_NATIVE_ARGUMENT(Bool, isLatin1, arguments->NativeArgAt(2)); |
601 intptr_t array_length = codeUnits.Length(); | 581 intptr_t array_length = codeUnits.Length(); |
602 intptr_t length_value = length.Value(); | 582 intptr_t length_value = length.Value(); |
603 if (length_value < 0 || length_value > array_length) { | 583 if (length_value < 0 || length_value > array_length) { |
604 Exceptions::ThrowRangeError("length", length, 0, array_length); | 584 Exceptions::ThrowRangeError("length", length, 0, array_length); |
605 } | 585 } |
606 const String& result = | 586 const String& result = |
607 isLatin1.value() | 587 isLatin1.value() |
608 ? String::Handle(OneByteString::New(length_value, Heap::kNew)) | 588 ? String::Handle(OneByteString::New(length_value, Heap::kNew)) |
609 : String::Handle(TwoByteString::New(length_value, Heap::kNew)); | 589 : String::Handle(TwoByteString::New(length_value, Heap::kNew)); |
610 NoSafepointScope no_safepoint; | 590 NoSafepointScope no_safepoint; |
611 | 591 |
612 uint16_t* data_position = reinterpret_cast<uint16_t*>(codeUnits.DataAddr(0)); | 592 uint16_t* data_position = reinterpret_cast<uint16_t*>(codeUnits.DataAddr(0)); |
613 String::Copy(result, 0, data_position, length_value); | 593 String::Copy(result, 0, data_position, length_value); |
614 return result.raw(); | 594 return result.raw(); |
615 } | 595 } |
616 | 596 |
617 } // namespace dart | 597 } // namespace dart |
OLD | NEW |