| 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 "vm/exceptions.h" | 7 #include "vm/exceptions.h" | 
| 8 #include "vm/native_entry.h" | 8 #include "vm/native_entry.h" | 
| 9 #include "vm/object.h" | 9 #include "vm/object.h" | 
| 10 #include "vm/symbols.h" | 10 #include "vm/symbols.h" | 
| 11 | 11 | 
| 12 namespace dart { | 12 namespace dart { | 
| 13 | 13 | 
| 14 DEFINE_NATIVE_ENTRY(StringBase_createFromUtf16, 1) { | 14 DEFINE_NATIVE_ENTRY(StringBase_createFromCodePoints, 1) { | 
| 15   GET_NATIVE_ARGUMENT(Array, a, arguments->NativeArgAt(0)); | 15   GET_NATIVE_ARGUMENT(Array, a, arguments->NativeArgAt(0)); | 
| 16   // TODO(srdjan): Check that parameterized type is an int. | 16   // TODO(srdjan): Check that parameterized type is an int. | 
| 17   Zone* zone = isolate->current_zone(); | 17   Zone* zone = isolate->current_zone(); | 
| 18   intptr_t array_len = a.Length(); | 18   intptr_t array_len = a.Length(); | 
| 19 | 19 | 
| 20   // Unbox the array and determine the maximum element width. | 20   // Unbox the array and determine the maximum element width. | 
| 21   bool is_one_byte_string = true; | 21   bool is_one_byte_string = true; | 
| 22   int32_t* utf32_array = zone->Alloc<int32_t>(array_len); | 22   intptr_t utf16_len = array_len; | 
|  | 23   uint32_t* utf32_array = zone->Alloc<uint32_t>(array_len); | 
| 23   Object& index_object = Object::Handle(isolate); | 24   Object& index_object = Object::Handle(isolate); | 
| 24   for (intptr_t i = 0; i < array_len; i++) { | 25   for (intptr_t i = 0; i < array_len; i++) { | 
| 25     index_object = a.At(i); | 26     index_object = a.At(i); | 
| 26     if (!index_object.IsSmi()) { | 27     if (!index_object.IsSmi()) { | 
| 27       GrowableArray<const Object*> args; | 28       GrowableArray<const Object*> args; | 
| 28       args.Add(&index_object); | 29       args.Add(&index_object); | 
| 29       Exceptions::ThrowByType(Exceptions::kArgument, args); | 30       Exceptions::ThrowByType(Exceptions::kArgument, args); | 
| 30     } | 31     } | 
| 31     intptr_t value = Smi::Cast(index_object).Value(); | 32     intptr_t value = Smi::Cast(index_object).Value(); | 
| 32     if (value > Utf16::kMaxCodeUnit) { | 33     if (value < 0) { | 
| 33       GrowableArray<const Object*> args; | 34       GrowableArray<const Object*> args; | 
| 34       Exceptions::ThrowByType(Exceptions::kArgument, args); | 35       Exceptions::ThrowByType(Exceptions::kArgument, args); | 
| 35     } else { | 36     } else { | 
| 36       if (value > 0x7F) { | 37       if (value > 0x7F) { | 
| 37         is_one_byte_string = false; | 38         is_one_byte_string = false; | 
| 38       } | 39       } | 
|  | 40       if (value > 0xFFFF) { | 
|  | 41         utf16_len += 1; | 
|  | 42       } | 
| 39     } | 43     } | 
| 40     utf32_array[i] = value; | 44     utf32_array[i] = value; | 
| 41   } | 45   } | 
| 42   if (is_one_byte_string) { | 46   if (is_one_byte_string) { | 
| 43     return OneByteString::New(utf32_array, array_len, Heap::kNew); | 47     return OneByteString::New(utf32_array, array_len, Heap::kNew); | 
| 44   } | 48   } | 
| 45   return TwoByteString::New(array_len, utf32_array, array_len, Heap::kNew); | 49   return TwoByteString::New(utf16_len, utf32_array, array_len, Heap::kNew); | 
| 46 } | 50 } | 
| 47 | 51 | 
| 48 | 52 | 
| 49 DEFINE_NATIVE_ENTRY(StringBase_substringUnchecked, 3) { | 53 DEFINE_NATIVE_ENTRY(StringBase_substringUnchecked, 3) { | 
| 50   GET_NATIVE_ARGUMENT(String, receiver, arguments->NativeArgAt(0)); | 54   GET_NATIVE_ARGUMENT(String, receiver, arguments->NativeArgAt(0)); | 
| 51   GET_NATIVE_ARGUMENT(Smi, start_obj, arguments->NativeArgAt(1)); | 55   GET_NATIVE_ARGUMENT(Smi, start_obj, arguments->NativeArgAt(1)); | 
| 52   GET_NATIVE_ARGUMENT(Smi, end_obj, arguments->NativeArgAt(2)); | 56   GET_NATIVE_ARGUMENT(Smi, end_obj, arguments->NativeArgAt(2)); | 
| 53 | 57 | 
| 54   intptr_t start = start_obj.Value(); | 58   intptr_t start = start_obj.Value(); | 
| 55   intptr_t end = end_obj.Value(); | 59   intptr_t end = end_obj.Value(); | 
| 56   return String::SubString(receiver, start, (end - start)); | 60   return String::SubString(receiver, start, (end - start)); | 
| 57 } | 61 } | 
| 58 | 62 | 
| 59 | 63 | 
| 60 DEFINE_NATIVE_ENTRY(String_getHashCode, 1) { | 64 DEFINE_NATIVE_ENTRY(String_getHashCode, 1) { | 
| 61   const String& receiver = String::CheckedHandle(arguments->NativeArgAt(0)); | 65   const String& receiver = String::CheckedHandle(arguments->NativeArgAt(0)); | 
| 62   intptr_t hash_val = receiver.Hash(); | 66   intptr_t hash_val = receiver.Hash(); | 
| 63   ASSERT(hash_val > 0); | 67   ASSERT(hash_val > 0); | 
| 64   ASSERT(Smi::IsValid(hash_val)); | 68   ASSERT(Smi::IsValid(hash_val)); | 
| 65   return Smi::New(hash_val); | 69   return Smi::New(hash_val); | 
| 66 } | 70 } | 
| 67 | 71 | 
| 68 | 72 | 
| 69 DEFINE_NATIVE_ENTRY(String_getLength, 1) { | 73 DEFINE_NATIVE_ENTRY(String_getLength, 1) { | 
| 70   const String& receiver = String::CheckedHandle(arguments->NativeArgAt(0)); | 74   const String& receiver = String::CheckedHandle(arguments->NativeArgAt(0)); | 
| 71   return Smi::New(receiver.Length()); | 75   return Smi::New(receiver.Length()); | 
| 72 } | 76 } | 
| 73 | 77 | 
| 74 | 78 | 
| 75 static int32_t StringCodeUnitAt(const String& str, const Integer& index) { | 79 static int32_t StringValueAt(const String& str, const Integer& index) { | 
| 76   if (index.IsSmi()) { | 80   if (index.IsSmi()) { | 
| 77     Smi& smi = Smi::Handle(); | 81     Smi& smi = Smi::Handle(); | 
| 78     smi ^= index.raw(); | 82     smi ^= index.raw(); | 
| 79     int32_t index = smi.Value(); | 83     int32_t index = smi.Value(); | 
| 80     if ((index < 0) || (index >= str.Length())) { | 84     if ((index < 0) || (index >= str.Length())) { | 
| 81       GrowableArray<const Object*> arguments; | 85       GrowableArray<const Object*> arguments; | 
| 82       arguments.Add(&smi); | 86       arguments.Add(&smi); | 
| 83       Exceptions::ThrowByType(Exceptions::kRange, arguments); | 87       Exceptions::ThrowByType(Exceptions::kRange, arguments); | 
| 84     } | 88     } | 
| 85     return str.CharAt(index); | 89     return str.CharAt(index); | 
| 86   } else { | 90   } else { | 
| 87     // An index larger than Smi is always illegal. | 91     // An index larger than Smi is always illegal. | 
| 88     GrowableArray<const Object*> arguments; | 92     GrowableArray<const Object*> arguments; | 
| 89     arguments.Add(&index); | 93     arguments.Add(&index); | 
| 90     Exceptions::ThrowByType(Exceptions::kRange, arguments); | 94     Exceptions::ThrowByType(Exceptions::kRange, arguments); | 
| 91     return 0; | 95     return 0; | 
| 92   } | 96   } | 
| 93 } | 97 } | 
| 94 | 98 | 
| 95 | 99 | 
| 96 DEFINE_NATIVE_ENTRY(String_charAt, 2) { | 100 DEFINE_NATIVE_ENTRY(String_charAt, 2) { | 
| 97   const String& receiver = String::CheckedHandle(arguments->NativeArgAt(0)); | 101   const String& receiver = String::CheckedHandle(arguments->NativeArgAt(0)); | 
| 98   GET_NATIVE_ARGUMENT(Integer, index, arguments->NativeArgAt(1)); | 102   GET_NATIVE_ARGUMENT(Integer, index, arguments->NativeArgAt(1)); | 
| 99   uint16_t value = StringCodeUnitAt(receiver, index); | 103   uint32_t value = StringValueAt(receiver, index); | 
| 100   // The VM does not GC interned strings, so we only create them for a | 104   ASSERT(value <= 0x10FFFF); | 
| 101   // restricted range. | 105   return Symbols::FromCharCode(value); | 
| 102   const int32_t kFrequentCharacterLimit = 0xFF; |  | 
| 103   if (value <= kFrequentCharacterLimit) { |  | 
| 104     return Symbols::FromCharCode(value); |  | 
| 105   } else { |  | 
| 106     return String::New(&value, 1); |  | 
| 107   } |  | 
| 108 } | 106 } | 
| 109 | 107 | 
| 110 | 108 DEFINE_NATIVE_ENTRY(String_charCodeAt, 2) { | 
| 111 DEFINE_NATIVE_ENTRY(String_codeUnitAt, 2) { |  | 
| 112   const String& receiver = String::CheckedHandle(arguments->NativeArgAt(0)); | 109   const String& receiver = String::CheckedHandle(arguments->NativeArgAt(0)); | 
| 113   GET_NATIVE_ARGUMENT(Integer, index, arguments->NativeArgAt(1)); | 110   GET_NATIVE_ARGUMENT(Integer, index, arguments->NativeArgAt(1)); | 
| 114   int32_t value = StringCodeUnitAt(receiver, index); | 111 | 
| 115   ASSERT(value <= Utf16::kMaxCodeUnit); | 112   int32_t value = StringValueAt(receiver, index); | 
|  | 113   ASSERT(value >= 0); | 
|  | 114   ASSERT(value <= 0x10FFFF); | 
| 116   return Smi::New(value); | 115   return Smi::New(value); | 
| 117 } | 116 } | 
| 118 | 117 | 
| 119 | 118 | 
| 120 DEFINE_NATIVE_ENTRY(String_concat, 2) { | 119 DEFINE_NATIVE_ENTRY(String_concat, 2) { | 
| 121   const String& receiver = String::CheckedHandle(arguments->NativeArgAt(0)); | 120   const String& receiver = String::CheckedHandle(arguments->NativeArgAt(0)); | 
| 122   GET_NATIVE_ARGUMENT(String, b, arguments->NativeArgAt(1)); | 121   GET_NATIVE_ARGUMENT(String, b, arguments->NativeArgAt(1)); | 
| 123   return String::Concat(receiver, b); | 122   return String::Concat(receiver, b); | 
| 124 } | 123 } | 
| 125 | 124 | 
| (...skipping 22 matching lines...) Expand all  Loading... | 
| 148     if (!elem.IsString()) { | 147     if (!elem.IsString()) { | 
| 149       GrowableArray<const Object*> args; | 148       GrowableArray<const Object*> args; | 
| 150       args.Add(&elem); | 149       args.Add(&elem); | 
| 151       Exceptions::ThrowByType(Exceptions::kArgument, args); | 150       Exceptions::ThrowByType(Exceptions::kArgument, args); | 
| 152     } | 151     } | 
| 153   } | 152   } | 
| 154   return String::ConcatAll(strings); | 153   return String::ConcatAll(strings); | 
| 155 } | 154 } | 
| 156 | 155 | 
| 157 }  // namespace dart | 156 }  // namespace dart | 
| OLD | NEW | 
|---|