| Index: src/runtime.cc
|
| diff --git a/src/runtime.cc b/src/runtime.cc
|
| index 93ec83fba8a445b54d25a1fe45447ec5dc0d784a..14e9a2c70a1ce3150101db77a984543655a82b5e 100644
|
| --- a/src/runtime.cc
|
| +++ b/src/runtime.cc
|
| @@ -4365,8 +4365,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringIndexOf) {
|
| if (!index->ToArrayIndex(&start_index)) return Smi::FromInt(-1);
|
|
|
| RUNTIME_ASSERT(start_index <= static_cast<uint32_t>(sub->length()));
|
| - int position =
|
| - Runtime::StringMatch(isolate, sub, pat, start_index);
|
| + int position = Runtime::StringMatch(isolate, sub, pat, start_index);
|
| return Smi::FromInt(position);
|
| }
|
|
|
| @@ -4466,13 +4465,13 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringLastIndexOf) {
|
|
|
|
|
| RUNTIME_FUNCTION(MaybeObject*, Runtime_StringLocaleCompare) {
|
| - SealHandleScope shs(isolate);
|
| + HandleScope handle_scope(isolate);
|
| ASSERT(args.length() == 2);
|
|
|
| - CONVERT_ARG_CHECKED(String, str1, 0);
|
| - CONVERT_ARG_CHECKED(String, str2, 1);
|
| + CONVERT_ARG_HANDLE_CHECKED(String, str1, 0);
|
| + CONVERT_ARG_HANDLE_CHECKED(String, str2, 1);
|
|
|
| - if (str1 == str2) return Smi::FromInt(0); // Equal.
|
| + if (str1.is_identical_to(str2)) return Smi::FromInt(0); // Equal.
|
| int str1_length = str1->length();
|
| int str2_length = str2->length();
|
|
|
| @@ -4492,21 +4491,17 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringLocaleCompare) {
|
| int d = str1->Get(0) - str2->Get(0);
|
| if (d != 0) return Smi::FromInt(d);
|
|
|
| - str1->TryFlatten();
|
| - str2->TryFlatten();
|
| + str1 = String::Flatten(str1);
|
| + str2 = String::Flatten(str2);
|
|
|
| - ConsStringIteratorOp* op1 =
|
| - isolate->runtime_state()->string_locale_compare_it1();
|
| - ConsStringIteratorOp* op2 =
|
| - isolate->runtime_state()->string_locale_compare_it2();
|
| - // TODO(dcarney) Can do array compares here more efficiently.
|
| - StringCharacterStream stream1(str1, op1);
|
| - StringCharacterStream stream2(str2, op2);
|
| + DisallowHeapAllocation no_gc;
|
| + String::FlatContent flat1 = str1->GetFlatContent();
|
| + String::FlatContent flat2 = str2->GetFlatContent();
|
|
|
| for (int i = 0; i < end; i++) {
|
| - uint16_t char1 = stream1.GetNext();
|
| - uint16_t char2 = stream2.GetNext();
|
| - if (char1 != char2) return Smi::FromInt(char1 - char2);
|
| + if (flat1.Get(i) != flat2.Get(i)) {
|
| + return Smi::FromInt(flat1.Get(i) - flat2.Get(i));
|
| + }
|
| }
|
|
|
| return Smi::FromInt(str1_length - str2_length);
|
| @@ -6073,8 +6068,10 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetArgumentsProperty) {
|
| }
|
|
|
| // Handle special arguments properties.
|
| - if (key->Equals(isolate->heap()->length_string())) return Smi::FromInt(n);
|
| - if (key->Equals(isolate->heap()->callee_string())) {
|
| + if (String::Equals(isolate->factory()->length_string(), key)) {
|
| + return Smi::FromInt(n);
|
| + }
|
| + if (String::Equals(isolate->factory()->callee_string(), key)) {
|
| JSFunction* function = frame->function();
|
| if (function->shared()->strict_mode() == STRICT) {
|
| return isolate->Throw(*isolate->factory()->NewTypeError(
|
| @@ -6174,17 +6171,18 @@ static int ParseDecimalInteger(const uint8_t*s, int from, int to) {
|
|
|
|
|
| RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToNumber) {
|
| - SealHandleScope shs(isolate);
|
| + HandleScope handle_scope(isolate);
|
| ASSERT(args.length() == 1);
|
| - CONVERT_ARG_CHECKED(String, subject, 0);
|
| - subject->TryFlatten();
|
| + CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
|
| + subject = String::Flatten(subject);
|
|
|
| // Fast case: short integer or some sorts of junk values.
|
| - int len = subject->length();
|
| if (subject->IsSeqOneByteString()) {
|
| + int len = subject->length();
|
| if (len == 0) return Smi::FromInt(0);
|
|
|
| - uint8_t const* data = SeqOneByteString::cast(subject)->GetChars();
|
| + DisallowHeapAllocation no_gc;
|
| + uint8_t const* data = Handle<SeqOneByteString>::cast(subject)->GetChars();
|
| bool minus = (data[0] == '-');
|
| int start_pos = (minus ? 1 : 0);
|
|
|
| @@ -6192,15 +6190,15 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToNumber) {
|
| return isolate->heap()->nan_value();
|
| } else if (data[start_pos] > '9') {
|
| // Fast check for a junk value. A valid string may start from a
|
| - // whitespace, a sign ('+' or '-'), the decimal point, a decimal digit or
|
| - // the 'I' character ('Infinity'). All of that have codes not greater than
|
| - // '9' except 'I' and .
|
| + // whitespace, a sign ('+' or '-'), the decimal point, a decimal digit
|
| + // or the 'I' character ('Infinity'). All of that have codes not greater
|
| + // than '9' except 'I' and .
|
| if (data[start_pos] != 'I' && data[start_pos] != 0xa0) {
|
| return isolate->heap()->nan_value();
|
| }
|
| } else if (len - start_pos < 10 && AreDigits(data, start_pos, len)) {
|
| - // The maximal/minimal smi has 10 digits. If the string has less digits we
|
| - // know it will fit into the smi-data type.
|
| + // The maximal/minimal smi has 10 digits. If the string has less digits
|
| + // we know it will fit into the smi-data type.
|
| int d = ParseDecimalInteger(data, start_pos, len);
|
| if (minus) {
|
| if (d == 0) return isolate->heap()->minus_zero_value();
|
| @@ -6229,8 +6227,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToNumber) {
|
| // Type", https://bugs.ecmascript.org/show_bug.cgi?id=1584
|
| flags |= ALLOW_OCTAL | ALLOW_BINARY;
|
| }
|
| - return isolate->heap()->NumberFromDouble(
|
| - StringToDouble(isolate->unicode_cache(), subject, flags));
|
| +
|
| + return *isolate->factory()->NewNumber(StringToDouble(
|
| + isolate->unicode_cache(), *subject, flags));
|
| }
|
|
|
|
|
| @@ -6304,29 +6303,40 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_BasicJSONStringify) {
|
|
|
|
|
| RUNTIME_FUNCTION(MaybeObject*, Runtime_StringParseInt) {
|
| - SealHandleScope shs(isolate);
|
| -
|
| - CONVERT_ARG_CHECKED(String, s, 0);
|
| + HandleScope handle_scope(isolate);
|
| + CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
|
| CONVERT_SMI_ARG_CHECKED(radix, 1);
|
| + RUNTIME_ASSERT(radix == 0 || (2 <= radix && radix <= 36));
|
|
|
| - s->TryFlatten();
|
| + subject = String::Flatten(subject);
|
| + double value;
|
|
|
| - RUNTIME_ASSERT(radix == 0 || (2 <= radix && radix <= 36));
|
| - double value = StringToInt(isolate->unicode_cache(), s, radix);
|
| - return isolate->heap()->NumberFromDouble(value);
|
| + { DisallowHeapAllocation no_gc;
|
| + String::FlatContent flat = subject->GetFlatContent();
|
| +
|
| + // ECMA-262 section 15.1.2.3, empty string is NaN
|
| + if (flat.IsAscii()) {
|
| + value = StringToInt(
|
| + isolate->unicode_cache(), flat.ToOneByteVector(), radix);
|
| + } else {
|
| + value = StringToInt(
|
| + isolate->unicode_cache(), flat.ToUC16Vector(), radix);
|
| + }
|
| + }
|
| +
|
| + return *isolate->factory()->NewNumber(value);
|
| }
|
|
|
|
|
| RUNTIME_FUNCTION(MaybeObject*, Runtime_StringParseFloat) {
|
| - SealHandleScope shs(isolate);
|
| - CONVERT_ARG_CHECKED(String, str, 0);
|
| + HandleScope shs(isolate);
|
| + CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
|
|
|
| - // ECMA-262 section 15.1.2.3, empty string is NaN
|
| - double value = StringToDouble(isolate->unicode_cache(),
|
| - str, ALLOW_TRAILING_JUNK, OS::nan_value());
|
| + subject = String::Flatten(subject);
|
| + double value = StringToDouble(
|
| + isolate->unicode_cache(), *subject, ALLOW_TRAILING_JUNK, OS::nan_value());
|
|
|
| - // Create a number object from the value.
|
| - return isolate->heap()->NumberFromDouble(value);
|
| + return *isolate->factory()->NewNumber(value);
|
| }
|
|
|
|
|
| @@ -7501,13 +7511,13 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberEquals) {
|
|
|
|
|
| RUNTIME_FUNCTION(MaybeObject*, Runtime_StringEquals) {
|
| - SealHandleScope shs(isolate);
|
| + HandleScope handle_scope(isolate);
|
| ASSERT(args.length() == 2);
|
|
|
| - CONVERT_ARG_CHECKED(String, x, 0);
|
| - CONVERT_ARG_CHECKED(String, y, 1);
|
| + CONVERT_ARG_HANDLE_CHECKED(String, x, 0);
|
| + CONVERT_ARG_HANDLE_CHECKED(String, y, 1);
|
|
|
| - bool not_equal = !x->Equals(y);
|
| + bool not_equal = !String::Equals(x, y);
|
| // This is slightly convoluted because the value that signifies
|
| // equality is 0 and inequality is 1 so we have to negate the result
|
| // from String::Equals.
|
| @@ -7608,27 +7618,33 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_SmiLexicographicCompare) {
|
| }
|
|
|
|
|
| -static Object* StringCharacterStreamCompare(RuntimeState* state,
|
| - String* x,
|
| - String* y) {
|
| - StringCharacterStream stream_x(x, state->string_iterator_compare_x());
|
| - StringCharacterStream stream_y(y, state->string_iterator_compare_y());
|
| - while (stream_x.HasMore() && stream_y.HasMore()) {
|
| - int d = stream_x.GetNext() - stream_y.GetNext();
|
| - if (d < 0) return Smi::FromInt(LESS);
|
| - else if (d > 0) return Smi::FromInt(GREATER);
|
| +RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_StringCompare) {
|
| + HandleScope handle_scope(isolate);
|
| + ASSERT(args.length() == 2);
|
| +
|
| + CONVERT_ARG_HANDLE_CHECKED(String, x, 0);
|
| + CONVERT_ARG_HANDLE_CHECKED(String, y, 1);
|
| +
|
| + isolate->counters()->string_compare_runtime()->Increment();
|
| +
|
| + // A few fast case tests before we flatten.
|
| + if (x.is_identical_to(y)) return Smi::FromInt(EQUAL);
|
| + if (y->length() == 0) {
|
| + if (x->length() == 0) return Smi::FromInt(EQUAL);
|
| + return Smi::FromInt(GREATER);
|
| + } else if (x->length() == 0) {
|
| + return Smi::FromInt(LESS);
|
| }
|
|
|
| - // x is (non-trivial) prefix of y:
|
| - if (stream_y.HasMore()) return Smi::FromInt(LESS);
|
| - // y is prefix of x:
|
| - return Smi::FromInt(stream_x.HasMore() ? GREATER : EQUAL);
|
| -}
|
| + int d = x->Get(0) - y->Get(0);
|
| + if (d < 0) return Smi::FromInt(LESS);
|
| + else if (d > 0) return Smi::FromInt(GREATER);
|
|
|
| + // Slow case.
|
| + x = String::Flatten(x);
|
| + y = String::Flatten(y);
|
|
|
| -static Object* FlatStringCompare(String* x, String* y) {
|
| - ASSERT(x->IsFlat());
|
| - ASSERT(y->IsFlat());
|
| + DisallowHeapAllocation no_gc;
|
| Object* equal_prefix_result = Smi::FromInt(EQUAL);
|
| int prefix_length = x->length();
|
| if (y->length() < prefix_length) {
|
| @@ -7638,7 +7654,6 @@ static Object* FlatStringCompare(String* x, String* y) {
|
| equal_prefix_result = Smi::FromInt(LESS);
|
| }
|
| int r;
|
| - DisallowHeapAllocation no_gc;
|
| String::FlatContent x_content = x->GetFlatContent();
|
| String::FlatContent y_content = y->GetFlatContent();
|
| if (x_content.IsAscii()) {
|
| @@ -7666,47 +7681,10 @@ static Object* FlatStringCompare(String* x, String* y) {
|
| } else {
|
| result = (r < 0) ? Smi::FromInt(LESS) : Smi::FromInt(GREATER);
|
| }
|
| - ASSERT(result ==
|
| - StringCharacterStreamCompare(x->GetIsolate()->runtime_state(), x, y));
|
| return result;
|
| }
|
|
|
|
|
| -RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_StringCompare) {
|
| - HandleScope shs(isolate);
|
| - ASSERT(args.length() == 2);
|
| -
|
| - CONVERT_ARG_CHECKED(String, x, 0);
|
| - CONVERT_ARG_CHECKED(String, y, 1);
|
| -
|
| - isolate->counters()->string_compare_runtime()->Increment();
|
| -
|
| - // A few fast case tests before we flatten.
|
| - if (x == y) return Smi::FromInt(EQUAL);
|
| - if (y->length() == 0) {
|
| - if (x->length() == 0) return Smi::FromInt(EQUAL);
|
| - return Smi::FromInt(GREATER);
|
| - } else if (x->length() == 0) {
|
| - return Smi::FromInt(LESS);
|
| - }
|
| -
|
| - int d = x->Get(0) - y->Get(0);
|
| - if (d < 0) return Smi::FromInt(LESS);
|
| - else if (d > 0) return Smi::FromInt(GREATER);
|
| -
|
| - Object* obj;
|
| - { MaybeObject* maybe_obj = isolate->heap()->PrepareForCompare(x);
|
| - if (!maybe_obj->ToObject(&obj)) return maybe_obj;
|
| - }
|
| - { MaybeObject* maybe_obj = isolate->heap()->PrepareForCompare(y);
|
| - if (!maybe_obj->ToObject(&obj)) return maybe_obj;
|
| - }
|
| -
|
| - return (x->IsFlat() && y->IsFlat()) ? FlatStringCompare(x, y)
|
| - : StringCharacterStreamCompare(isolate->runtime_state(), x, y);
|
| -}
|
| -
|
| -
|
| #define RUNTIME_UNARY_MATH(Name, name) \
|
| RUNTIME_FUNCTION(MaybeObject*, Runtime_Math##Name) { \
|
| SealHandleScope shs(isolate); \
|
| @@ -11583,7 +11561,7 @@ static bool SetContextLocalValue(Isolate* isolate,
|
| Handle<Object> new_value) {
|
| for (int i = 0; i < scope_info->ContextLocalCount(); i++) {
|
| Handle<String> next_name(scope_info->ContextLocalName(i));
|
| - if (variable_name->Equals(*next_name)) {
|
| + if (String::Equals(variable_name, next_name)) {
|
| VariableMode mode;
|
| InitializationFlag init_flag;
|
| int context_index =
|
| @@ -11615,7 +11593,8 @@ static bool SetLocalVariableValue(Isolate* isolate,
|
|
|
| // Parameters.
|
| for (int i = 0; i < scope_info->ParameterCount(); ++i) {
|
| - if (scope_info->ParameterName(i)->Equals(*variable_name)) {
|
| + HandleScope scope(isolate);
|
| + if (String::Equals(handle(scope_info->ParameterName(i)), variable_name)) {
|
| frame->SetParameterValue(i, *new_value);
|
| // Argument might be shadowed in heap context, don't stop here.
|
| default_result = true;
|
| @@ -11624,7 +11603,8 @@ static bool SetLocalVariableValue(Isolate* isolate,
|
|
|
| // Stack locals.
|
| for (int i = 0; i < scope_info->StackLocalCount(); ++i) {
|
| - if (scope_info->StackLocalName(i)->Equals(*variable_name)) {
|
| + HandleScope scope(isolate);
|
| + if (String::Equals(handle(scope_info->StackLocalName(i)), variable_name)) {
|
| frame->SetExpression(i, *new_value);
|
| return true;
|
| }
|
| @@ -11765,7 +11745,7 @@ static bool SetCatchVariableValue(Isolate* isolate,
|
| Handle<Object> new_value) {
|
| ASSERT(context->IsCatchContext());
|
| Handle<String> name(String::cast(context->extension()));
|
| - if (!name->Equals(*variable_name)) {
|
| + if (!String::Equals(name, variable_name)) {
|
| return false;
|
| }
|
| context->set(Context::THROWN_OBJECT_INDEX, *new_value);
|
|
|