OLD | NEW |
---|---|
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/objects.h" | 5 #include "src/objects.h" |
6 | 6 |
7 #include <iomanip> | 7 #include <iomanip> |
8 #include <sstream> | 8 #include <sstream> |
9 | 9 |
10 #include "src/accessors.h" | 10 #include "src/accessors.h" |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
83 constructor = handle( | 83 constructor = handle( |
84 JSFunction::cast(native_context->get(constructor_function_index)), | 84 JSFunction::cast(native_context->get(constructor_function_index)), |
85 isolate); | 85 isolate); |
86 } | 86 } |
87 Handle<JSObject> result = isolate->factory()->NewJSObject(constructor); | 87 Handle<JSObject> result = isolate->factory()->NewJSObject(constructor); |
88 Handle<JSValue>::cast(result)->set_value(*object); | 88 Handle<JSValue>::cast(result)->set_value(*object); |
89 return result; | 89 return result; |
90 } | 90 } |
91 | 91 |
92 | 92 |
93 MaybeHandle<Name> Object::ToName(Isolate* isolate, Handle<Object> object) { | 93 // static |
94 if (object->IsName()) { | 94 MaybeHandle<Object> Object::ToNumber(Isolate* isolate, Handle<Object> input) { |
95 return Handle<Name>::cast(object); | 95 while (true) { |
96 } else { | 96 if (input->IsNumber()) { |
97 Handle<Object> converted; | 97 return input; |
98 ASSIGN_RETURN_ON_EXCEPTION(isolate, converted, | 98 } |
99 Execution::ToString(isolate, object), Name); | 99 if (input->IsOddball()) { |
100 return Handle<Name>::cast(converted); | 100 return handle(Handle<Oddball>::cast(input)->to_number(), isolate); |
101 } | |
102 if (input->IsString()) { | |
103 return String::ToNumber(Handle<String>::cast(input)); | |
104 } | |
105 if (input->IsSymbol()) { | |
106 THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kSymbolToNumber), | |
107 Object); | |
108 } | |
109 if (input->IsSimd128Value()) { | |
110 THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kSimdToNumber), | |
111 Object); | |
112 } | |
113 ASSIGN_RETURN_ON_EXCEPTION( | |
114 isolate, input, JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(input), | |
115 ToPrimitiveHint::kNumber), | |
116 Object); | |
101 } | 117 } |
102 } | 118 } |
103 | 119 |
120 | |
121 // static | |
122 MaybeHandle<String> Object::ToString(Isolate* isolate, Handle<Object> input) { | |
123 while (true) { | |
124 if (input->IsString()) { | |
125 return Handle<String>::cast(input); | |
126 } | |
127 if (input->IsOddball()) { | |
128 return handle(Handle<Oddball>::cast(input)->to_string(), isolate); | |
129 } | |
130 if (input->IsNumber()) { | |
131 return isolate->factory()->NumberToString(input); | |
132 } | |
133 if (input->IsSymbol()) { | |
134 THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kSymbolToString), | |
135 String); | |
136 } | |
137 if (input->IsSimd128Value()) { | |
138 return Simd128Value::ToString(Handle<Simd128Value>::cast(input)); | |
139 } | |
140 ASSIGN_RETURN_ON_EXCEPTION( | |
141 isolate, input, JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(input), | |
142 ToPrimitiveHint::kString), | |
143 String); | |
144 } | |
145 } | |
146 | |
104 | 147 |
105 bool Object::BooleanValue() { | 148 bool Object::BooleanValue() { |
106 if (IsBoolean()) return IsTrue(); | 149 if (IsBoolean()) return IsTrue(); |
107 if (IsSmi()) return Smi::cast(this)->value() != 0; | 150 if (IsSmi()) return Smi::cast(this)->value() != 0; |
108 if (IsUndefined() || IsNull()) return false; | 151 if (IsUndefined() || IsNull()) return false; |
109 if (IsUndetectableObject()) return false; // Undetectable object is false. | 152 if (IsUndetectableObject()) return false; // Undetectable object is false. |
110 if (IsString()) return String::cast(this)->length() != 0; | 153 if (IsString()) return String::cast(this)->length() != 0; |
111 if (IsHeapNumber()) return HeapNumber::cast(this)->HeapNumberBooleanValue(); | 154 if (IsHeapNumber()) return HeapNumber::cast(this)->HeapNumberBooleanValue(); |
112 if (IsSimd128Value()) return true; // Simd value types evaluate to true. | |
113 return true; | 155 return true; |
114 } | 156 } |
115 | 157 |
116 | 158 |
117 bool Object::StrictEquals(Object* that) { | 159 bool Object::StrictEquals(Object* that) { |
118 if (this->IsNumber()) { | 160 if (this->IsNumber()) { |
119 if (!that->IsNumber()) return false; | 161 if (!that->IsNumber()) return false; |
120 double const x = this->Number(); | 162 double const x = this->Number(); |
121 double const y = that->Number(); | 163 double const y = that->Number(); |
122 // Must check explicitly for NaN:s on Windows, but -0 works fine. | 164 // Must check explicitly for NaN:s on Windows, but -0 works fine. |
(...skipping 27 matching lines...) Expand all Loading... | |
150 if (js_object->map()->is_access_check_needed()) return false; | 192 if (js_object->map()->is_access_check_needed()) return false; |
151 auto isolate = js_object->GetIsolate(); | 193 auto isolate = js_object->GetIsolate(); |
152 // TODO(dcarney): this should just be read from the symbol registry so as not | 194 // TODO(dcarney): this should just be read from the symbol registry so as not |
153 // to be context dependent. | 195 // to be context dependent. |
154 auto key = isolate->factory()->promise_status_symbol(); | 196 auto key = isolate->factory()->promise_status_symbol(); |
155 // Shouldn't be possible to throw here. | 197 // Shouldn't be possible to throw here. |
156 return JSObject::HasRealNamedProperty(js_object, key).FromJust(); | 198 return JSObject::HasRealNamedProperty(js_object, key).FromJust(); |
157 } | 199 } |
158 | 200 |
159 | 201 |
202 // static | |
203 MaybeHandle<Object> Object::GetMethod(Handle<JSReceiver> receiver, | |
204 Handle<Name> name) { | |
205 Handle<Object> func; | |
206 Isolate* isolate = receiver->GetIsolate(); | |
207 ASSIGN_RETURN_ON_EXCEPTION(isolate, func, | |
208 JSReceiver::GetProperty(receiver, name), Object); | |
209 if (func->IsNull() || func->IsUndefined()) { | |
210 return isolate->factory()->undefined_value(); | |
211 } | |
212 if (!func->IsCallable()) { | |
213 // TODO(bmeurer): Better error message here? | |
214 THROW_NEW_ERROR(isolate, | |
215 NewTypeError(MessageTemplate::kCalledNonCallable, func), | |
216 Object); | |
217 } | |
218 return func; | |
219 } | |
220 | |
221 | |
160 MaybeHandle<Object> Object::GetProperty(LookupIterator* it, | 222 MaybeHandle<Object> Object::GetProperty(LookupIterator* it, |
161 LanguageMode language_mode) { | 223 LanguageMode language_mode) { |
162 for (; it->IsFound(); it->Next()) { | 224 for (; it->IsFound(); it->Next()) { |
163 switch (it->state()) { | 225 switch (it->state()) { |
164 case LookupIterator::NOT_FOUND: | 226 case LookupIterator::NOT_FOUND: |
165 case LookupIterator::TRANSITION: | 227 case LookupIterator::TRANSITION: |
166 UNREACHABLE(); | 228 UNREACHABLE(); |
167 case LookupIterator::JSPROXY: | 229 case LookupIterator::JSPROXY: |
168 return JSProxy::GetPropertyWithHandler( | 230 return JSProxy::GetPropertyWithHandler( |
169 it->GetHolder<JSProxy>(), it->GetReceiver(), it->GetName()); | 231 it->GetHolder<JSProxy>(), it->GetReceiver(), it->GetName()); |
(...skipping 1308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1478 #define READ_INT32_FIELD(p, offset) \ | 1540 #define READ_INT32_FIELD(p, offset) \ |
1479 (*reinterpret_cast<const int32_t*>(FIELD_ADDR_CONST(p, offset))) | 1541 (*reinterpret_cast<const int32_t*>(FIELD_ADDR_CONST(p, offset))) |
1480 | 1542 |
1481 #define READ_INT64_FIELD(p, offset) \ | 1543 #define READ_INT64_FIELD(p, offset) \ |
1482 (*reinterpret_cast<const int64_t*>(FIELD_ADDR_CONST(p, offset))) | 1544 (*reinterpret_cast<const int64_t*>(FIELD_ADDR_CONST(p, offset))) |
1483 | 1545 |
1484 #define READ_BYTE_FIELD(p, offset) \ | 1546 #define READ_BYTE_FIELD(p, offset) \ |
1485 (*reinterpret_cast<const byte*>(FIELD_ADDR_CONST(p, offset))) | 1547 (*reinterpret_cast<const byte*>(FIELD_ADDR_CONST(p, offset))) |
1486 | 1548 |
1487 | 1549 |
1550 // static | |
1551 Handle<String> Simd128Value::ToString(Handle<Simd128Value> input) { | |
1552 #define SIMD128_TYPE(TYPE, Type, type, lane_count, lane_type) \ | |
1553 if (input->Is##Type()) return Type::ToString(Handle<Type>::cast(input)); | |
1554 SIMD128_TYPES(SIMD128_TYPE) | |
1555 #undef SIMD128_TYPE | |
1556 UNREACHABLE(); | |
1557 return Handle<String>::null(); | |
1558 } | |
1559 | |
1560 | |
1561 // static | |
1562 Handle<String> Float32x4::ToString(Handle<Float32x4> input) { | |
1563 Isolate* const isolate = input->GetIsolate(); | |
1564 char arr[100]; | |
1565 Vector<char> buffer(arr, arraysize(arr)); | |
1566 std::ostringstream os; | |
1567 os << "SIMD.Float32x4(" | |
1568 << std::string(DoubleToCString(input->get_lane(0), buffer)) << ", " | |
1569 << std::string(DoubleToCString(input->get_lane(1), buffer)) << ", " | |
1570 << std::string(DoubleToCString(input->get_lane(2), buffer)) << ", " | |
1571 << std::string(DoubleToCString(input->get_lane(3), buffer)) << ")"; | |
1572 return isolate->factory()->NewStringFromAsciiChecked(os.str().c_str()); | |
1573 } | |
1574 | |
1575 | |
1576 #define SIMD128_BOOL_TO_STRING(Type, lane_count) \ | |
1577 Handle<String> Type::ToString(Handle<Type> input) { \ | |
1578 Isolate* const isolate = input->GetIsolate(); \ | |
1579 std::ostringstream os; \ | |
1580 os << "SIMD." #Type "("; \ | |
1581 os << (input->get_lane(0) ? "true" : "false"); \ | |
1582 for (int i = 1; i < lane_count; i++) { \ | |
1583 os << ", " << (input->get_lane(i) ? "true" : "false"); \ | |
1584 } \ | |
1585 os << ")"; \ | |
1586 return isolate->factory()->NewStringFromAsciiChecked(os.str().c_str()); \ | |
1587 } | |
1588 SIMD128_BOOL_TO_STRING(Bool32x4, 4) | |
1589 SIMD128_BOOL_TO_STRING(Bool16x8, 8) | |
1590 SIMD128_BOOL_TO_STRING(Bool8x16, 16) | |
1591 #undef SIMD128_BOOL_TO_STRING | |
1592 | |
1593 | |
1594 #define SIMD128_INT_TO_STRING(Type, lane_count) \ | |
1595 Handle<String> Type::ToString(Handle<Type> input) { \ | |
1596 Isolate* const isolate = input->GetIsolate(); \ | |
1597 char arr[100]; \ | |
1598 Vector<char> buffer(arr, arraysize(arr)); \ | |
1599 std::ostringstream os; \ | |
1600 os << "SIMD." #Type "("; \ | |
1601 os << IntToCString(input->get_lane(0), buffer); \ | |
1602 for (int i = 1; i < lane_count; i++) { \ | |
1603 os << ", " << IntToCString(input->get_lane(i), buffer); \ | |
1604 } \ | |
1605 os << ")"; \ | |
1606 return isolate->factory()->NewStringFromAsciiChecked(os.str().c_str()); \ | |
1607 } | |
1608 SIMD128_INT_TO_STRING(Int32x4, 4) | |
1609 SIMD128_INT_TO_STRING(Uint32x4, 4) | |
1610 SIMD128_INT_TO_STRING(Int16x8, 8) | |
1611 SIMD128_INT_TO_STRING(Uint16x8, 8) | |
1612 SIMD128_INT_TO_STRING(Int8x16, 16) | |
1613 SIMD128_INT_TO_STRING(Uint8x16, 16) | |
1614 #undef SIMD128_INT_TO_STRING | |
1615 | |
1616 | |
1488 bool Simd128Value::BitwiseEquals(const Simd128Value* other) const { | 1617 bool Simd128Value::BitwiseEquals(const Simd128Value* other) const { |
1489 return READ_INT64_FIELD(this, kValueOffset) == | 1618 return READ_INT64_FIELD(this, kValueOffset) == |
1490 READ_INT64_FIELD(other, kValueOffset) && | 1619 READ_INT64_FIELD(other, kValueOffset) && |
1491 READ_INT64_FIELD(this, kValueOffset + kInt64Size) == | 1620 READ_INT64_FIELD(this, kValueOffset + kInt64Size) == |
1492 READ_INT64_FIELD(other, kValueOffset + kInt64Size); | 1621 READ_INT64_FIELD(other, kValueOffset + kInt64Size); |
1493 } | 1622 } |
1494 | 1623 |
1495 | 1624 |
1496 uint32_t Simd128Value::Hash() const { | 1625 uint32_t Simd128Value::Hash() const { |
1497 uint32_t seed = v8::internal::kZeroHashSeed; | 1626 uint32_t seed = v8::internal::kZeroHashSeed; |
(...skipping 1774 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3272 (it->IsElement() || | 3401 (it->IsElement() || |
3273 !it->isolate()->IsInternallyUsedPropertyName(it->name())); | 3402 !it->isolate()->IsInternallyUsedPropertyName(it->name())); |
3274 MaybeHandle<Object> maybe_old; | 3403 MaybeHandle<Object> maybe_old; |
3275 if (is_observed) maybe_old = it->GetDataValue(); | 3404 if (is_observed) maybe_old = it->GetDataValue(); |
3276 | 3405 |
3277 Handle<Object> to_assign = value; | 3406 Handle<Object> to_assign = value; |
3278 // Convert the incoming value to a number for storing into typed arrays. | 3407 // Convert the incoming value to a number for storing into typed arrays. |
3279 if (it->IsElement() && receiver->HasFixedTypedArrayElements()) { | 3408 if (it->IsElement() && receiver->HasFixedTypedArrayElements()) { |
3280 if (!value->IsNumber() && !value->IsUndefined()) { | 3409 if (!value->IsNumber() && !value->IsUndefined()) { |
3281 ASSIGN_RETURN_ON_EXCEPTION(it->isolate(), to_assign, | 3410 ASSIGN_RETURN_ON_EXCEPTION(it->isolate(), to_assign, |
3282 Execution::ToNumber(it->isolate(), value), | 3411 Object::ToNumber(it->isolate(), value), |
3283 Object); | 3412 Object); |
3284 // ToNumber above might modify the receiver, causing the cached | 3413 // ToNumber above might modify the receiver, causing the cached |
3285 // holder_map to mismatch the actual holder->map() after this point. | 3414 // holder_map to mismatch the actual holder->map() after this point. |
3286 // Reload the map to be in consistent state. Other cached state cannot | 3415 // Reload the map to be in consistent state. Other cached state cannot |
3287 // have been invalidated since typed array elements cannot be reconfigured | 3416 // have been invalidated since typed array elements cannot be reconfigured |
3288 // in any way. | 3417 // in any way. |
3289 it->ReloadHolderMap(); | 3418 it->ReloadHolderMap(); |
3290 | 3419 |
3291 // We have to recheck the length. However, it can only change if the | 3420 // We have to recheck the length. However, it can only change if the |
3292 // underlying buffer was neutered, so just check that. | 3421 // underlying buffer was neutered, so just check that. |
(...skipping 2581 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5874 AllocationSiteUsageContext* site_context, | 6003 AllocationSiteUsageContext* site_context, |
5875 DeepCopyHints hints) { | 6004 DeepCopyHints hints) { |
5876 JSObjectWalkVisitor<AllocationSiteUsageContext> v(site_context, true, hints); | 6005 JSObjectWalkVisitor<AllocationSiteUsageContext> v(site_context, true, hints); |
5877 MaybeHandle<JSObject> copy = v.StructureWalk(object); | 6006 MaybeHandle<JSObject> copy = v.StructureWalk(object); |
5878 Handle<JSObject> for_assert; | 6007 Handle<JSObject> for_assert; |
5879 DCHECK(!copy.ToHandle(&for_assert) || !for_assert.is_identical_to(object)); | 6008 DCHECK(!copy.ToHandle(&for_assert) || !for_assert.is_identical_to(object)); |
5880 return copy; | 6009 return copy; |
5881 } | 6010 } |
5882 | 6011 |
5883 | 6012 |
6013 // static | |
6014 MaybeHandle<Object> JSReceiver::ToPrimitive(Handle<JSReceiver> receiver, | |
6015 ToPrimitiveHint hint) { | |
6016 Isolate* const isolate = receiver->GetIsolate(); | |
6017 Handle<Object> exotic_to_prim; | |
6018 ASSIGN_RETURN_ON_EXCEPTION( | |
6019 isolate, exotic_to_prim, | |
6020 GetMethod(receiver, isolate->factory()->to_primitive_symbol()), Object); | |
adamk
2015/08/28 19:36:15
This is going to change behavior when invoking ToP
| |
6021 if (!exotic_to_prim->IsUndefined()) { | |
6022 Handle<Object> hint_string; | |
6023 switch (hint) { | |
6024 case ToPrimitiveHint::kDefault: | |
6025 hint_string = isolate->factory()->default_string(); | |
6026 break; | |
6027 case ToPrimitiveHint::kNumber: | |
6028 hint_string = isolate->factory()->number_string(); | |
6029 break; | |
6030 case ToPrimitiveHint::kString: | |
6031 hint_string = isolate->factory()->string_string(); | |
6032 break; | |
6033 } | |
6034 Handle<Object> result; | |
6035 ASSIGN_RETURN_ON_EXCEPTION( | |
6036 isolate, result, | |
6037 Execution::Call(isolate, exotic_to_prim, receiver, 1, &hint_string), | |
6038 Object); | |
6039 if (result->IsPrimitive()) return result; | |
6040 THROW_NEW_ERROR(isolate, | |
6041 NewTypeError(MessageTemplate::kCannotConvertToPrimitive), | |
6042 Object); | |
6043 } | |
6044 return OrdinaryToPrimitive(receiver, | |
6045 (hint == ToPrimitiveHint::kString) | |
6046 ? isolate->factory()->string_string() | |
6047 : isolate->factory()->number_string()); | |
6048 } | |
6049 | |
6050 | |
6051 // static | |
6052 MaybeHandle<Object> JSReceiver::OrdinaryToPrimitive(Handle<JSReceiver> receiver, | |
6053 Handle<String> hint) { | |
6054 Isolate* const isolate = receiver->GetIsolate(); | |
6055 Handle<String> method_names[2]; | |
6056 if (hint.is_identical_to(isolate->factory()->number_string())) { | |
6057 method_names[0] = isolate->factory()->valueOf_string(); | |
6058 method_names[1] = isolate->factory()->toString_string(); | |
6059 } else { | |
6060 DCHECK(hint.is_identical_to(isolate->factory()->string_string())); | |
6061 method_names[0] = isolate->factory()->toString_string(); | |
6062 method_names[1] = isolate->factory()->valueOf_string(); | |
6063 } | |
6064 for (Handle<String> name : method_names) { | |
6065 Handle<Object> method; | |
6066 ASSIGN_RETURN_ON_EXCEPTION(isolate, method, | |
6067 JSReceiver::GetProperty(receiver, name), Object); | |
6068 if (method->IsCallable()) { | |
6069 Handle<Object> result; | |
6070 ASSIGN_RETURN_ON_EXCEPTION( | |
6071 isolate, result, Execution::Call(isolate, method, receiver, 0, NULL), | |
6072 Object); | |
6073 if (result->IsPrimitive()) return result; | |
6074 } | |
6075 } | |
6076 THROW_NEW_ERROR(isolate, | |
6077 NewTypeError(MessageTemplate::kCannotConvertToPrimitive), | |
6078 Object); | |
6079 } | |
6080 | |
6081 | |
5884 // Tests for the fast common case for property enumeration: | 6082 // Tests for the fast common case for property enumeration: |
5885 // - This object and all prototypes has an enum cache (which means that | 6083 // - This object and all prototypes has an enum cache (which means that |
5886 // it is no proxy, has no interceptors and needs no access checks). | 6084 // it is no proxy, has no interceptors and needs no access checks). |
5887 // - This object has no elements. | 6085 // - This object has no elements. |
5888 // - No prototype has enumerable properties/elements. | 6086 // - No prototype has enumerable properties/elements. |
5889 bool JSReceiver::IsSimpleEnum() { | 6087 bool JSReceiver::IsSimpleEnum() { |
5890 for (PrototypeIterator iter(GetIsolate(), this, | 6088 for (PrototypeIterator iter(GetIsolate(), this, |
5891 PrototypeIterator::START_AT_RECEIVER); | 6089 PrototypeIterator::START_AT_RECEIVER); |
5892 !iter.IsAtEnd(); iter.Advance()) { | 6090 !iter.IsAtEnd(); iter.Advance()) { |
5893 if (!iter.GetCurrent()->IsJSObject()) return false; | 6091 if (!iter.GetCurrent()->IsJSObject()) return false; |
(...skipping 2251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
8145 } | 8343 } |
8146 #endif | 8344 #endif |
8147 | 8345 |
8148 | 8346 |
8149 bool String::LooksValid() { | 8347 bool String::LooksValid() { |
8150 if (!GetIsolate()->heap()->Contains(this)) return false; | 8348 if (!GetIsolate()->heap()->Contains(this)) return false; |
8151 return true; | 8349 return true; |
8152 } | 8350 } |
8153 | 8351 |
8154 | 8352 |
8353 namespace { | |
8354 | |
8355 bool AreDigits(const uint8_t* s, int from, int to) { | |
8356 for (int i = from; i < to; i++) { | |
8357 if (s[i] < '0' || s[i] > '9') return false; | |
8358 } | |
8359 | |
8360 return true; | |
8361 } | |
8362 | |
8363 | |
8364 int ParseDecimalInteger(const uint8_t* s, int from, int to) { | |
8365 DCHECK(to - from < 10); // Overflow is not possible. | |
8366 DCHECK(from < to); | |
8367 int d = s[from] - '0'; | |
8368 | |
8369 for (int i = from + 1; i < to; i++) { | |
8370 d = 10 * d + (s[i] - '0'); | |
8371 } | |
8372 | |
8373 return d; | |
8374 } | |
8375 | |
8376 } // namespace | |
8377 | |
8378 | |
8379 // static | |
8380 Handle<Object> String::ToNumber(Handle<String> subject) { | |
8381 Isolate* const isolate = subject->GetIsolate(); | |
8382 | |
8383 // Flatten {subject} string first. | |
8384 subject = String::Flatten(subject); | |
8385 | |
8386 // Fast array index case. | |
8387 uint32_t index; | |
8388 if (subject->AsArrayIndex(&index)) { | |
8389 return isolate->factory()->NewNumberFromUint(index); | |
8390 } | |
8391 | |
8392 // Fast case: short integer or some sorts of junk values. | |
8393 if (subject->IsSeqOneByteString()) { | |
8394 int len = subject->length(); | |
8395 if (len == 0) return handle(Smi::FromInt(0), isolate); | |
8396 | |
8397 DisallowHeapAllocation no_gc; | |
8398 uint8_t const* data = Handle<SeqOneByteString>::cast(subject)->GetChars(); | |
8399 bool minus = (data[0] == '-'); | |
8400 int start_pos = (minus ? 1 : 0); | |
8401 | |
8402 if (start_pos == len) { | |
8403 return isolate->factory()->nan_value(); | |
8404 } else if (data[start_pos] > '9') { | |
8405 // Fast check for a junk value. A valid string may start from a | |
8406 // whitespace, a sign ('+' or '-'), the decimal point, a decimal digit | |
8407 // or the 'I' character ('Infinity'). All of that have codes not greater | |
8408 // than '9' except 'I' and . | |
8409 if (data[start_pos] != 'I' && data[start_pos] != 0xa0) { | |
8410 return isolate->factory()->nan_value(); | |
8411 } | |
8412 } else if (len - start_pos < 10 && AreDigits(data, start_pos, len)) { | |
8413 // The maximal/minimal smi has 10 digits. If the string has less digits | |
8414 // we know it will fit into the smi-data type. | |
8415 int d = ParseDecimalInteger(data, start_pos, len); | |
8416 if (minus) { | |
8417 if (d == 0) return isolate->factory()->minus_zero_value(); | |
8418 d = -d; | |
8419 } else if (!subject->HasHashCode() && len <= String::kMaxArrayIndexSize && | |
8420 (len == 1 || data[0] != '0')) { | |
8421 // String hash is not calculated yet but all the data are present. | |
8422 // Update the hash field to speed up sequential convertions. | |
8423 uint32_t hash = StringHasher::MakeArrayIndexHash(d, len); | |
8424 #ifdef DEBUG | |
8425 subject->Hash(); // Force hash calculation. | |
8426 DCHECK_EQ(static_cast<int>(subject->hash_field()), | |
8427 static_cast<int>(hash)); | |
8428 #endif | |
8429 subject->set_hash_field(hash); | |
8430 } | |
8431 return handle(Smi::FromInt(d), isolate); | |
8432 } | |
8433 } | |
8434 | |
8435 // Slower case. | |
8436 int flags = ALLOW_HEX | ALLOW_OCTAL | ALLOW_BINARY; | |
8437 return isolate->factory()->NewNumber( | |
8438 StringToDouble(isolate->unicode_cache(), subject, flags)); | |
8439 } | |
8440 | |
8441 | |
8155 String::FlatContent String::GetFlatContent() { | 8442 String::FlatContent String::GetFlatContent() { |
8156 DCHECK(!AllowHeapAllocation::IsAllowed()); | 8443 DCHECK(!AllowHeapAllocation::IsAllowed()); |
8157 int length = this->length(); | 8444 int length = this->length(); |
8158 StringShape shape(this); | 8445 StringShape shape(this); |
8159 String* string = this; | 8446 String* string = this; |
8160 int offset = 0; | 8447 int offset = 0; |
8161 if (shape.representation_tag() == kConsStringTag) { | 8448 if (shape.representation_tag() == kConsStringTag) { |
8162 ConsString* cons = ConsString::cast(string); | 8449 ConsString* cons = ConsString::cast(string); |
8163 if (cons->second()->length() != 0) { | 8450 if (cons->second()->length() != 0) { |
8164 return FlatContent(); | 8451 return FlatContent(); |
(...skipping 7674 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
15839 if (cell->value() != *new_value) { | 16126 if (cell->value() != *new_value) { |
15840 cell->set_value(*new_value); | 16127 cell->set_value(*new_value); |
15841 Isolate* isolate = cell->GetIsolate(); | 16128 Isolate* isolate = cell->GetIsolate(); |
15842 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 16129 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
15843 isolate, DependentCode::kPropertyCellChangedGroup); | 16130 isolate, DependentCode::kPropertyCellChangedGroup); |
15844 } | 16131 } |
15845 } | 16132 } |
15846 | 16133 |
15847 } // namespace internal | 16134 } // namespace internal |
15848 } // namespace v8 | 16135 } // namespace v8 |
OLD | NEW |