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 |