Chromium Code Reviews| 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 |