Chromium Code Reviews| 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" |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 22 intptr_t utf16_len = array_len; | 22 intptr_t utf16_len = array_len; |
| 23 uint32_t* utf32_array = zone->Alloc<uint32_t>(array_len); | 23 uint32_t* utf32_array = zone->Alloc<uint32_t>(array_len); |
| 24 Object& index_object = Object::Handle(isolate); | 24 Object& index_object = Object::Handle(isolate); |
| 25 for (intptr_t i = 0; i < array_len; i++) { | 25 for (intptr_t i = 0; i < array_len; i++) { |
| 26 index_object = a.At(i); | 26 index_object = a.At(i); |
| 27 if (!index_object.IsSmi()) { | 27 if (!index_object.IsSmi()) { |
| 28 GrowableArray<const Object*> args; | 28 GrowableArray<const Object*> args; |
| 29 args.Add(&index_object); | 29 args.Add(&index_object); |
| 30 Exceptions::ThrowByType(Exceptions::kArgument, args); | 30 Exceptions::ThrowByType(Exceptions::kArgument, args); |
| 31 } | 31 } |
| 32 intptr_t value = Smi::Cast(index_object).Value(); | 32 uint32_t value = Smi::Cast(index_object).Value(); |
|
floitsch
2012/11/08 15:28:21
I don't think this works.
On 64bit machines a Smi
erikcorry
2012/11/15 13:28:25
Done.
| |
| 33 if (value < 0) { | 33 if (Utf16::IsSurrogate(value) || |
| 34 value > Utf16::kMaxCodePoint) { | |
| 34 GrowableArray<const Object*> args; | 35 GrowableArray<const Object*> args; |
| 35 Exceptions::ThrowByType(Exceptions::kArgument, args); | 36 Exceptions::ThrowByType(Exceptions::kArgument, args); |
| 36 } else { | 37 } else { |
| 37 if (value > 0x7F) { | 38 if (value > 0x7F) { |
| 38 is_one_byte_string = false; | 39 is_one_byte_string = false; |
| 39 } | 40 } |
| 40 if (value > 0xFFFF) { | 41 if (value > Utf16::kMaxCodeUnit) { |
| 41 utf16_len += 1; | 42 utf16_len += 1; |
| 42 } | 43 } |
| 43 } | 44 } |
| 44 utf32_array[i] = value; | 45 utf32_array[i] = value; |
| 45 } | 46 } |
| 46 if (is_one_byte_string) { | 47 if (is_one_byte_string) { |
| 47 return OneByteString::New(utf32_array, array_len, Heap::kNew); | 48 return OneByteString::New(utf32_array, array_len, Heap::kNew); |
| 48 } | 49 } |
| 49 return TwoByteString::New(utf16_len, utf32_array, array_len, Heap::kNew); | 50 return TwoByteString::New(utf16_len, utf32_array, array_len, Heap::kNew); |
| 50 } | 51 } |
| 51 | 52 |
| 52 | 53 |
| 54 DEFINE_NATIVE_ENTRY(StringBase_createFromCodeUnits, 1) { | |
| 55 GET_NATIVE_ARGUMENT(Array, a, arguments->At(0)); | |
| 56 // TODO(srdjan): Check that parameterized type is an int. | |
| 57 Zone* zone = isolate->current_zone(); | |
| 58 intptr_t array_len = a.Length(); | |
| 59 | |
| 60 // Unbox the array and determine the maximum element width. | |
| 61 bool is_one_byte_string = true; | |
| 62 uint32_t* utf32_array = zone->Alloc<uint32_t>(array_len); | |
| 63 Object& index_object = Object::Handle(isolate); | |
| 64 for (intptr_t i = 0; i < array_len; i++) { | |
| 65 index_object = a.At(i); | |
| 66 if (!index_object.IsSmi()) { | |
| 67 GrowableArray<const Object*> args; | |
| 68 args.Add(&index_object); | |
| 69 Exceptions::ThrowByType(Exceptions::kArgument, args); | |
| 70 } | |
| 71 uint32_t value = Smi::Cast(index_object).Value(); | |
|
floitsch
2012/11/08 15:28:21
ditto.
erikcorry
2012/11/15 13:28:25
This code is now gone.
| |
| 72 if (value > Utf16::kMaxCodeUnit) { | |
| 73 GrowableArray<const Object*> args; | |
| 74 Exceptions::ThrowByType(Exceptions::kArgument, args); | |
| 75 } else { | |
| 76 if (value > 0x7F) { | |
| 77 is_one_byte_string = false; | |
| 78 } | |
| 79 } | |
| 80 utf32_array[i] = value; | |
| 81 } | |
| 82 if (is_one_byte_string) { | |
| 83 return OneByteString::New(utf32_array, array_len, Heap::kNew); | |
| 84 } | |
| 85 return TwoByteString::New(array_len, utf32_array, array_len, Heap::kNew); | |
| 86 } | |
| 87 | |
| 88 | |
| 53 DEFINE_NATIVE_ENTRY(StringBase_substringUnchecked, 3) { | 89 DEFINE_NATIVE_ENTRY(StringBase_substringUnchecked, 3) { |
| 54 GET_NATIVE_ARGUMENT(String, receiver, arguments->At(0)); | 90 GET_NATIVE_ARGUMENT(String, receiver, arguments->At(0)); |
| 55 GET_NATIVE_ARGUMENT(Smi, start_obj, arguments->At(1)); | 91 GET_NATIVE_ARGUMENT(Smi, start_obj, arguments->At(1)); |
| 56 GET_NATIVE_ARGUMENT(Smi, end_obj, arguments->At(2)); | 92 GET_NATIVE_ARGUMENT(Smi, end_obj, arguments->At(2)); |
| 57 | 93 |
| 58 intptr_t start = start_obj.Value(); | 94 intptr_t start = start_obj.Value(); |
| 59 intptr_t end = end_obj.Value(); | 95 intptr_t end = end_obj.Value(); |
| 60 return String::SubString(receiver, start, (end - start)); | 96 return String::SubString(receiver, start, (end - start)); |
| 61 } | 97 } |
| 62 | 98 |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 90 } else { | 126 } else { |
| 91 // An index larger than Smi is always illegal. | 127 // An index larger than Smi is always illegal. |
| 92 GrowableArray<const Object*> arguments; | 128 GrowableArray<const Object*> arguments; |
| 93 arguments.Add(&index); | 129 arguments.Add(&index); |
| 94 Exceptions::ThrowByType(Exceptions::kRange, arguments); | 130 Exceptions::ThrowByType(Exceptions::kRange, arguments); |
| 95 return 0; | 131 return 0; |
| 96 } | 132 } |
| 97 } | 133 } |
| 98 | 134 |
| 99 | 135 |
| 136 static int32_t StringCodeUnitAt(const String& str, const Integer& index) { | |
| 137 if (index.IsSmi()) { | |
| 138 Smi& smi = Smi::Handle(); | |
| 139 smi ^= index.raw(); | |
| 140 int32_t index = smi.Value(); | |
| 141 if ((index < 0) || (index >= str.Length())) { | |
| 142 GrowableArray<const Object*> arguments; | |
| 143 arguments.Add(&smi); | |
| 144 Exceptions::ThrowByType(Exceptions::kRange, arguments); | |
| 145 } | |
| 146 return str.CodeUnitAt(index); | |
| 147 } else { | |
| 148 // An index larger than Smi is always illegal. | |
| 149 GrowableArray<const Object*> arguments; | |
| 150 arguments.Add(&index); | |
| 151 Exceptions::ThrowByType(Exceptions::kRange, arguments); | |
| 152 return 0; | |
| 153 } | |
| 154 } | |
| 155 | |
| 156 | |
| 100 DEFINE_NATIVE_ENTRY(String_charAt, 2) { | 157 DEFINE_NATIVE_ENTRY(String_charAt, 2) { |
| 101 const String& receiver = String::CheckedHandle(arguments->At(0)); | 158 const String& receiver = String::CheckedHandle(arguments->At(0)); |
| 102 GET_NATIVE_ARGUMENT(Integer, index, arguments->At(1)); | 159 GET_NATIVE_ARGUMENT(Integer, index, arguments->At(1)); |
| 103 uint32_t value = StringValueAt(receiver, index); | 160 uint32_t value = StringValueAt(receiver, index); |
| 104 ASSERT(value <= 0x10FFFF); | 161 if (value <= Utf16::kMaxCodeUnit) { |
|
floitsch
2012/11/08 15:28:21
As discussed: This should just return a String wit
erikcorry
2012/11/15 13:28:25
Done.
| |
| 105 return Symbols::New(&value, 1); | 162 return Symbols::New(&value, 1); |
|
cshapiro
2012/11/09 04:43:57
This is generally not a good idea as the intern ta
erikcorry
2012/11/12 20:22:17
It already interned character strings, I did not c
cshapiro
2012/11/12 21:51:13
Yes, what you say is all true. This change is an
erikcorry
2012/11/15 13:28:25
I fixed it so it only interns ASCII characters.
| |
| 163 } | |
| 164 ASSERT(value <= Utf16::kMaxCodePoint); | |
| 165 uint32_t values[2]; | |
| 166 values[0] = Utf16::LeadFromCodePoint(value); | |
| 167 values[1] = Utf16::TrailFromCodePoint(value); | |
| 168 return Symbols::New(&values[0], 2); | |
| 106 } | 169 } |
| 107 | 170 |
| 171 | |
| 108 DEFINE_NATIVE_ENTRY(String_charCodeAt, 2) { | 172 DEFINE_NATIVE_ENTRY(String_charCodeAt, 2) { |
| 109 const String& receiver = String::CheckedHandle(arguments->At(0)); | 173 const String& receiver = String::CheckedHandle(arguments->At(0)); |
| 110 GET_NATIVE_ARGUMENT(Integer, index, arguments->At(1)); | 174 GET_NATIVE_ARGUMENT(Integer, index, arguments->At(1)); |
| 111 int32_t value = StringValueAt(receiver, index); | 175 uint32_t value = StringValueAt(receiver, index); |
| 112 ASSERT(value >= 0); | 176 ASSERT(value <= Utf16::kMaxCodePoint); |
| 113 ASSERT(value <= 0x10FFFF); | |
| 114 return Smi::New(value); | 177 return Smi::New(value); |
| 115 } | 178 } |
| 116 | 179 |
| 180 | |
| 181 DEFINE_NATIVE_ENTRY(String_codeUnitAt, 2) { | |
| 182 const String& receiver = String::CheckedHandle(arguments->At(0)); | |
| 183 GET_NATIVE_ARGUMENT(Integer, index, arguments->At(1)); | |
| 184 uint32_t value = StringCodeUnitAt(receiver, index); | |
| 185 ASSERT(value <= Utf16::kMaxCodeUnit); | |
| 186 return Smi::New(value); | |
| 187 } | |
| 188 | |
| 117 | 189 |
| 118 DEFINE_NATIVE_ENTRY(String_concat, 2) { | 190 DEFINE_NATIVE_ENTRY(String_concat, 2) { |
| 119 const String& receiver = String::CheckedHandle(arguments->At(0)); | 191 const String& receiver = String::CheckedHandle(arguments->At(0)); |
| 120 GET_NATIVE_ARGUMENT(String, b, arguments->At(1)); | 192 GET_NATIVE_ARGUMENT(String, b, arguments->At(1)); |
| 121 return String::Concat(receiver, b); | 193 return String::Concat(receiver, b); |
| 122 } | 194 } |
| 123 | 195 |
| 124 | 196 |
| 125 DEFINE_NATIVE_ENTRY(String_toLowerCase, 1) { | 197 DEFINE_NATIVE_ENTRY(String_toLowerCase, 1) { |
| 126 const String& receiver = String::CheckedHandle(arguments->At(0)); | 198 const String& receiver = String::CheckedHandle(arguments->At(0)); |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 150 if (!elem.IsString()) { | 222 if (!elem.IsString()) { |
| 151 GrowableArray<const Object*> args; | 223 GrowableArray<const Object*> args; |
| 152 args.Add(&elem); | 224 args.Add(&elem); |
| 153 Exceptions::ThrowByType(Exceptions::kArgument, args); | 225 Exceptions::ThrowByType(Exceptions::kArgument, args); |
| 154 } | 226 } |
| 155 } | 227 } |
| 156 return String::ConcatAll(strings); | 228 return String::ConcatAll(strings); |
| 157 } | 229 } |
| 158 | 230 |
| 159 } // namespace dart | 231 } // namespace dart |
| OLD | NEW |