| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 4347 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4358 ASSERT(args.length() == 3); | 4358 ASSERT(args.length() == 3); |
| 4359 | 4359 |
| 4360 CONVERT_ARG_HANDLE_CHECKED(String, sub, 0); | 4360 CONVERT_ARG_HANDLE_CHECKED(String, sub, 0); |
| 4361 CONVERT_ARG_HANDLE_CHECKED(String, pat, 1); | 4361 CONVERT_ARG_HANDLE_CHECKED(String, pat, 1); |
| 4362 | 4362 |
| 4363 Object* index = args[2]; | 4363 Object* index = args[2]; |
| 4364 uint32_t start_index; | 4364 uint32_t start_index; |
| 4365 if (!index->ToArrayIndex(&start_index)) return Smi::FromInt(-1); | 4365 if (!index->ToArrayIndex(&start_index)) return Smi::FromInt(-1); |
| 4366 | 4366 |
| 4367 RUNTIME_ASSERT(start_index <= static_cast<uint32_t>(sub->length())); | 4367 RUNTIME_ASSERT(start_index <= static_cast<uint32_t>(sub->length())); |
| 4368 int position = | 4368 int position = Runtime::StringMatch(isolate, sub, pat, start_index); |
| 4369 Runtime::StringMatch(isolate, sub, pat, start_index); | |
| 4370 return Smi::FromInt(position); | 4369 return Smi::FromInt(position); |
| 4371 } | 4370 } |
| 4372 | 4371 |
| 4373 | 4372 |
| 4374 template <typename schar, typename pchar> | 4373 template <typename schar, typename pchar> |
| 4375 static int StringMatchBackwards(Vector<const schar> subject, | 4374 static int StringMatchBackwards(Vector<const schar> subject, |
| 4376 Vector<const pchar> pattern, | 4375 Vector<const pchar> pattern, |
| 4377 int idx) { | 4376 int idx) { |
| 4378 int pattern_length = pattern.length(); | 4377 int pattern_length = pattern.length(); |
| 4379 ASSERT(pattern_length >= 1); | 4378 ASSERT(pattern_length >= 1); |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4459 pat_vector, | 4458 pat_vector, |
| 4460 start_index); | 4459 start_index); |
| 4461 } | 4460 } |
| 4462 } | 4461 } |
| 4463 | 4462 |
| 4464 return Smi::FromInt(position); | 4463 return Smi::FromInt(position); |
| 4465 } | 4464 } |
| 4466 | 4465 |
| 4467 | 4466 |
| 4468 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringLocaleCompare) { | 4467 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringLocaleCompare) { |
| 4469 SealHandleScope shs(isolate); | 4468 HandleScope handle_scope(isolate); |
| 4470 ASSERT(args.length() == 2); | 4469 ASSERT(args.length() == 2); |
| 4471 | 4470 |
| 4472 CONVERT_ARG_CHECKED(String, str1, 0); | 4471 CONVERT_ARG_HANDLE_CHECKED(String, str1, 0); |
| 4473 CONVERT_ARG_CHECKED(String, str2, 1); | 4472 CONVERT_ARG_HANDLE_CHECKED(String, str2, 1); |
| 4474 | 4473 |
| 4475 if (str1 == str2) return Smi::FromInt(0); // Equal. | 4474 if (str1.is_identical_to(str2)) return Smi::FromInt(0); // Equal. |
| 4476 int str1_length = str1->length(); | 4475 int str1_length = str1->length(); |
| 4477 int str2_length = str2->length(); | 4476 int str2_length = str2->length(); |
| 4478 | 4477 |
| 4479 // Decide trivial cases without flattening. | 4478 // Decide trivial cases without flattening. |
| 4480 if (str1_length == 0) { | 4479 if (str1_length == 0) { |
| 4481 if (str2_length == 0) return Smi::FromInt(0); // Equal. | 4480 if (str2_length == 0) return Smi::FromInt(0); // Equal. |
| 4482 return Smi::FromInt(-str2_length); | 4481 return Smi::FromInt(-str2_length); |
| 4483 } else { | 4482 } else { |
| 4484 if (str2_length == 0) return Smi::FromInt(str1_length); | 4483 if (str2_length == 0) return Smi::FromInt(str1_length); |
| 4485 } | 4484 } |
| 4486 | 4485 |
| 4487 int end = str1_length < str2_length ? str1_length : str2_length; | 4486 int end = str1_length < str2_length ? str1_length : str2_length; |
| 4488 | 4487 |
| 4489 // No need to flatten if we are going to find the answer on the first | 4488 // No need to flatten if we are going to find the answer on the first |
| 4490 // character. At this point we know there is at least one character | 4489 // character. At this point we know there is at least one character |
| 4491 // in each string, due to the trivial case handling above. | 4490 // in each string, due to the trivial case handling above. |
| 4492 int d = str1->Get(0) - str2->Get(0); | 4491 int d = str1->Get(0) - str2->Get(0); |
| 4493 if (d != 0) return Smi::FromInt(d); | 4492 if (d != 0) return Smi::FromInt(d); |
| 4494 | 4493 |
| 4495 str1->TryFlatten(); | 4494 str1 = String::Flatten(str1); |
| 4496 str2->TryFlatten(); | 4495 str2 = String::Flatten(str2); |
| 4497 | 4496 |
| 4498 ConsStringIteratorOp* op1 = | 4497 DisallowHeapAllocation no_gc; |
| 4499 isolate->runtime_state()->string_locale_compare_it1(); | 4498 String::FlatContent flat1 = str1->GetFlatContent(); |
| 4500 ConsStringIteratorOp* op2 = | 4499 String::FlatContent flat2 = str2->GetFlatContent(); |
| 4501 isolate->runtime_state()->string_locale_compare_it2(); | |
| 4502 // TODO(dcarney) Can do array compares here more efficiently. | |
| 4503 StringCharacterStream stream1(str1, op1); | |
| 4504 StringCharacterStream stream2(str2, op2); | |
| 4505 | 4500 |
| 4506 for (int i = 0; i < end; i++) { | 4501 for (int i = 0; i < end; i++) { |
| 4507 uint16_t char1 = stream1.GetNext(); | 4502 if (flat1.Get(i) != flat2.Get(i)) { |
| 4508 uint16_t char2 = stream2.GetNext(); | 4503 return Smi::FromInt(flat1.Get(i) - flat2.Get(i)); |
| 4509 if (char1 != char2) return Smi::FromInt(char1 - char2); | 4504 } |
| 4510 } | 4505 } |
| 4511 | 4506 |
| 4512 return Smi::FromInt(str1_length - str2_length); | 4507 return Smi::FromInt(str1_length - str2_length); |
| 4513 } | 4508 } |
| 4514 | 4509 |
| 4515 | 4510 |
| 4516 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_SubString) { | 4511 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_SubString) { |
| 4517 HandleScope scope(isolate); | 4512 HandleScope scope(isolate); |
| 4518 ASSERT(args.length() == 3); | 4513 ASSERT(args.length() == 3); |
| 4519 | 4514 |
| (...skipping 1546 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6066 } else { | 6061 } else { |
| 6067 Handle<Object> initial_prototype(isolate->initial_object_prototype()); | 6062 Handle<Object> initial_prototype(isolate->initial_object_prototype()); |
| 6068 Handle<Object> result = | 6063 Handle<Object> result = |
| 6069 Object::GetElement(isolate, initial_prototype, index); | 6064 Object::GetElement(isolate, initial_prototype, index); |
| 6070 RETURN_IF_EMPTY_HANDLE(isolate, result); | 6065 RETURN_IF_EMPTY_HANDLE(isolate, result); |
| 6071 return *result; | 6066 return *result; |
| 6072 } | 6067 } |
| 6073 } | 6068 } |
| 6074 | 6069 |
| 6075 // Handle special arguments properties. | 6070 // Handle special arguments properties. |
| 6076 if (key->Equals(isolate->heap()->length_string())) return Smi::FromInt(n); | 6071 if (String::Equals(isolate->factory()->length_string(), key)) { |
| 6077 if (key->Equals(isolate->heap()->callee_string())) { | 6072 return Smi::FromInt(n); |
| 6073 } |
| 6074 if (String::Equals(isolate->factory()->callee_string(), key)) { |
| 6078 JSFunction* function = frame->function(); | 6075 JSFunction* function = frame->function(); |
| 6079 if (function->shared()->strict_mode() == STRICT) { | 6076 if (function->shared()->strict_mode() == STRICT) { |
| 6080 return isolate->Throw(*isolate->factory()->NewTypeError( | 6077 return isolate->Throw(*isolate->factory()->NewTypeError( |
| 6081 "strict_arguments_callee", HandleVector<Object>(NULL, 0))); | 6078 "strict_arguments_callee", HandleVector<Object>(NULL, 0))); |
| 6082 } | 6079 } |
| 6083 return function; | 6080 return function; |
| 6084 } | 6081 } |
| 6085 | 6082 |
| 6086 // Lookup in the initial Object.prototype object. | 6083 // Lookup in the initial Object.prototype object. |
| 6087 return isolate->initial_object_prototype()->GetProperty(*key); | 6084 return isolate->initial_object_prototype()->GetProperty(*key); |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6167 | 6164 |
| 6168 for (int i = from + 1; i < to; i++) { | 6165 for (int i = from + 1; i < to; i++) { |
| 6169 d = 10 * d + (s[i] - '0'); | 6166 d = 10 * d + (s[i] - '0'); |
| 6170 } | 6167 } |
| 6171 | 6168 |
| 6172 return d; | 6169 return d; |
| 6173 } | 6170 } |
| 6174 | 6171 |
| 6175 | 6172 |
| 6176 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToNumber) { | 6173 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToNumber) { |
| 6177 SealHandleScope shs(isolate); | 6174 HandleScope handle_scope(isolate); |
| 6178 ASSERT(args.length() == 1); | 6175 ASSERT(args.length() == 1); |
| 6179 CONVERT_ARG_CHECKED(String, subject, 0); | 6176 CONVERT_ARG_HANDLE_CHECKED(String, subject, 0); |
| 6180 subject->TryFlatten(); | 6177 subject = String::Flatten(subject); |
| 6181 | 6178 |
| 6182 // Fast case: short integer or some sorts of junk values. | 6179 // Fast case: short integer or some sorts of junk values. |
| 6183 int len = subject->length(); | |
| 6184 if (subject->IsSeqOneByteString()) { | 6180 if (subject->IsSeqOneByteString()) { |
| 6181 int len = subject->length(); |
| 6185 if (len == 0) return Smi::FromInt(0); | 6182 if (len == 0) return Smi::FromInt(0); |
| 6186 | 6183 |
| 6187 uint8_t const* data = SeqOneByteString::cast(subject)->GetChars(); | 6184 DisallowHeapAllocation no_gc; |
| 6185 uint8_t const* data = Handle<SeqOneByteString>::cast(subject)->GetChars(); |
| 6188 bool minus = (data[0] == '-'); | 6186 bool minus = (data[0] == '-'); |
| 6189 int start_pos = (minus ? 1 : 0); | 6187 int start_pos = (minus ? 1 : 0); |
| 6190 | 6188 |
| 6191 if (start_pos == len) { | 6189 if (start_pos == len) { |
| 6192 return isolate->heap()->nan_value(); | 6190 return isolate->heap()->nan_value(); |
| 6193 } else if (data[start_pos] > '9') { | 6191 } else if (data[start_pos] > '9') { |
| 6194 // Fast check for a junk value. A valid string may start from a | 6192 // Fast check for a junk value. A valid string may start from a |
| 6195 // whitespace, a sign ('+' or '-'), the decimal point, a decimal digit or | 6193 // whitespace, a sign ('+' or '-'), the decimal point, a decimal digit |
| 6196 // the 'I' character ('Infinity'). All of that have codes not greater than | 6194 // or the 'I' character ('Infinity'). All of that have codes not greater |
| 6197 // '9' except 'I' and . | 6195 // than '9' except 'I' and . |
| 6198 if (data[start_pos] != 'I' && data[start_pos] != 0xa0) { | 6196 if (data[start_pos] != 'I' && data[start_pos] != 0xa0) { |
| 6199 return isolate->heap()->nan_value(); | 6197 return isolate->heap()->nan_value(); |
| 6200 } | 6198 } |
| 6201 } else if (len - start_pos < 10 && AreDigits(data, start_pos, len)) { | 6199 } else if (len - start_pos < 10 && AreDigits(data, start_pos, len)) { |
| 6202 // The maximal/minimal smi has 10 digits. If the string has less digits we | 6200 // The maximal/minimal smi has 10 digits. If the string has less digits |
| 6203 // know it will fit into the smi-data type. | 6201 // we know it will fit into the smi-data type. |
| 6204 int d = ParseDecimalInteger(data, start_pos, len); | 6202 int d = ParseDecimalInteger(data, start_pos, len); |
| 6205 if (minus) { | 6203 if (minus) { |
| 6206 if (d == 0) return isolate->heap()->minus_zero_value(); | 6204 if (d == 0) return isolate->heap()->minus_zero_value(); |
| 6207 d = -d; | 6205 d = -d; |
| 6208 } else if (!subject->HasHashCode() && | 6206 } else if (!subject->HasHashCode() && |
| 6209 len <= String::kMaxArrayIndexSize && | 6207 len <= String::kMaxArrayIndexSize && |
| 6210 (len == 1 || data[0] != '0')) { | 6208 (len == 1 || data[0] != '0')) { |
| 6211 // String hash is not calculated yet but all the data are present. | 6209 // String hash is not calculated yet but all the data are present. |
| 6212 // Update the hash field to speed up sequential convertions. | 6210 // Update the hash field to speed up sequential convertions. |
| 6213 uint32_t hash = StringHasher::MakeArrayIndexHash(d, len); | 6211 uint32_t hash = StringHasher::MakeArrayIndexHash(d, len); |
| 6214 #ifdef DEBUG | 6212 #ifdef DEBUG |
| 6215 subject->Hash(); // Force hash calculation. | 6213 subject->Hash(); // Force hash calculation. |
| 6216 ASSERT_EQ(static_cast<int>(subject->hash_field()), | 6214 ASSERT_EQ(static_cast<int>(subject->hash_field()), |
| 6217 static_cast<int>(hash)); | 6215 static_cast<int>(hash)); |
| 6218 #endif | 6216 #endif |
| 6219 subject->set_hash_field(hash); | 6217 subject->set_hash_field(hash); |
| 6220 } | 6218 } |
| 6221 return Smi::FromInt(d); | 6219 return Smi::FromInt(d); |
| 6222 } | 6220 } |
| 6223 } | 6221 } |
| 6224 | 6222 |
| 6225 // Slower case. | 6223 // Slower case. |
| 6226 int flags = ALLOW_HEX; | 6224 int flags = ALLOW_HEX; |
| 6227 if (FLAG_harmony_numeric_literals) { | 6225 if (FLAG_harmony_numeric_literals) { |
| 6228 // The current spec draft has not updated "ToNumber Applied to the String | 6226 // The current spec draft has not updated "ToNumber Applied to the String |
| 6229 // Type", https://bugs.ecmascript.org/show_bug.cgi?id=1584 | 6227 // Type", https://bugs.ecmascript.org/show_bug.cgi?id=1584 |
| 6230 flags |= ALLOW_OCTAL | ALLOW_BINARY; | 6228 flags |= ALLOW_OCTAL | ALLOW_BINARY; |
| 6231 } | 6229 } |
| 6232 return isolate->heap()->NumberFromDouble( | 6230 |
| 6233 StringToDouble(isolate->unicode_cache(), subject, flags)); | 6231 return *isolate->factory()->NewNumber(StringToDouble( |
| 6232 isolate->unicode_cache(), *subject, flags)); |
| 6234 } | 6233 } |
| 6235 | 6234 |
| 6236 | 6235 |
| 6237 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewString) { | 6236 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewString) { |
| 6238 SealHandleScope shs(isolate); | 6237 SealHandleScope shs(isolate); |
| 6239 CONVERT_SMI_ARG_CHECKED(length, 0); | 6238 CONVERT_SMI_ARG_CHECKED(length, 0); |
| 6240 CONVERT_BOOLEAN_ARG_CHECKED(is_one_byte, 1); | 6239 CONVERT_BOOLEAN_ARG_CHECKED(is_one_byte, 1); |
| 6241 if (length == 0) return isolate->heap()->empty_string(); | 6240 if (length == 0) return isolate->heap()->empty_string(); |
| 6242 if (is_one_byte) { | 6241 if (is_one_byte) { |
| 6243 return isolate->heap()->AllocateRawOneByteString(length); | 6242 return isolate->heap()->AllocateRawOneByteString(length); |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6297 | 6296 |
| 6298 RUNTIME_FUNCTION(MaybeObject*, Runtime_BasicJSONStringify) { | 6297 RUNTIME_FUNCTION(MaybeObject*, Runtime_BasicJSONStringify) { |
| 6299 HandleScope scope(isolate); | 6298 HandleScope scope(isolate); |
| 6300 ASSERT(args.length() == 1); | 6299 ASSERT(args.length() == 1); |
| 6301 BasicJsonStringifier stringifier(isolate); | 6300 BasicJsonStringifier stringifier(isolate); |
| 6302 return stringifier.Stringify(Handle<Object>(args[0], isolate)); | 6301 return stringifier.Stringify(Handle<Object>(args[0], isolate)); |
| 6303 } | 6302 } |
| 6304 | 6303 |
| 6305 | 6304 |
| 6306 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringParseInt) { | 6305 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringParseInt) { |
| 6307 SealHandleScope shs(isolate); | 6306 HandleScope handle_scope(isolate); |
| 6307 CONVERT_ARG_HANDLE_CHECKED(String, subject, 0); |
| 6308 CONVERT_SMI_ARG_CHECKED(radix, 1); |
| 6309 RUNTIME_ASSERT(radix == 0 || (2 <= radix && radix <= 36)); |
| 6308 | 6310 |
| 6309 CONVERT_ARG_CHECKED(String, s, 0); | 6311 subject = String::Flatten(subject); |
| 6310 CONVERT_SMI_ARG_CHECKED(radix, 1); | 6312 double value; |
| 6311 | 6313 |
| 6312 s->TryFlatten(); | 6314 { DisallowHeapAllocation no_gc; |
| 6315 String::FlatContent flat = subject->GetFlatContent(); |
| 6313 | 6316 |
| 6314 RUNTIME_ASSERT(radix == 0 || (2 <= radix && radix <= 36)); | 6317 // ECMA-262 section 15.1.2.3, empty string is NaN |
| 6315 double value = StringToInt(isolate->unicode_cache(), s, radix); | 6318 if (flat.IsAscii()) { |
| 6316 return isolate->heap()->NumberFromDouble(value); | 6319 value = StringToInt( |
| 6320 isolate->unicode_cache(), flat.ToOneByteVector(), radix); |
| 6321 } else { |
| 6322 value = StringToInt( |
| 6323 isolate->unicode_cache(), flat.ToUC16Vector(), radix); |
| 6324 } |
| 6325 } |
| 6326 |
| 6327 return *isolate->factory()->NewNumber(value); |
| 6317 } | 6328 } |
| 6318 | 6329 |
| 6319 | 6330 |
| 6320 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringParseFloat) { | 6331 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringParseFloat) { |
| 6321 SealHandleScope shs(isolate); | 6332 HandleScope shs(isolate); |
| 6322 CONVERT_ARG_CHECKED(String, str, 0); | 6333 CONVERT_ARG_HANDLE_CHECKED(String, subject, 0); |
| 6323 | 6334 |
| 6324 // ECMA-262 section 15.1.2.3, empty string is NaN | 6335 subject = String::Flatten(subject); |
| 6325 double value = StringToDouble(isolate->unicode_cache(), | 6336 double value = StringToDouble( |
| 6326 str, ALLOW_TRAILING_JUNK, OS::nan_value()); | 6337 isolate->unicode_cache(), *subject, ALLOW_TRAILING_JUNK, OS::nan_value()); |
| 6327 | 6338 |
| 6328 // Create a number object from the value. | 6339 return *isolate->factory()->NewNumber(value); |
| 6329 return isolate->heap()->NumberFromDouble(value); | |
| 6330 } | 6340 } |
| 6331 | 6341 |
| 6332 | 6342 |
| 6333 static inline bool ToUpperOverflows(uc32 character) { | 6343 static inline bool ToUpperOverflows(uc32 character) { |
| 6334 // y with umlauts and the micro sign are the only characters that stop | 6344 // y with umlauts and the micro sign are the only characters that stop |
| 6335 // fitting into one-byte when converting to uppercase. | 6345 // fitting into one-byte when converting to uppercase. |
| 6336 static const uc32 yuml_code = 0xff; | 6346 static const uc32 yuml_code = 0xff; |
| 6337 static const uc32 micro_code = 0xb5; | 6347 static const uc32 micro_code = 0xb5; |
| 6338 return (character == yuml_code || character == micro_code); | 6348 return (character == yuml_code || character == micro_code); |
| 6339 } | 6349 } |
| (...skipping 1154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7494 if ((fpclassify(x) == FP_ZERO) && (fpclassify(y) == FP_ZERO)) { | 7504 if ((fpclassify(x) == FP_ZERO) && (fpclassify(y) == FP_ZERO)) { |
| 7495 result = Smi::FromInt(EQUAL); | 7505 result = Smi::FromInt(EQUAL); |
| 7496 } else { | 7506 } else { |
| 7497 result = Smi::FromInt(NOT_EQUAL); | 7507 result = Smi::FromInt(NOT_EQUAL); |
| 7498 } | 7508 } |
| 7499 return result; | 7509 return result; |
| 7500 } | 7510 } |
| 7501 | 7511 |
| 7502 | 7512 |
| 7503 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringEquals) { | 7513 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringEquals) { |
| 7504 SealHandleScope shs(isolate); | 7514 HandleScope handle_scope(isolate); |
| 7505 ASSERT(args.length() == 2); | 7515 ASSERT(args.length() == 2); |
| 7506 | 7516 |
| 7507 CONVERT_ARG_CHECKED(String, x, 0); | 7517 CONVERT_ARG_HANDLE_CHECKED(String, x, 0); |
| 7508 CONVERT_ARG_CHECKED(String, y, 1); | 7518 CONVERT_ARG_HANDLE_CHECKED(String, y, 1); |
| 7509 | 7519 |
| 7510 bool not_equal = !x->Equals(y); | 7520 bool not_equal = !String::Equals(x, y); |
| 7511 // This is slightly convoluted because the value that signifies | 7521 // This is slightly convoluted because the value that signifies |
| 7512 // equality is 0 and inequality is 1 so we have to negate the result | 7522 // equality is 0 and inequality is 1 so we have to negate the result |
| 7513 // from String::Equals. | 7523 // from String::Equals. |
| 7514 ASSERT(not_equal == 0 || not_equal == 1); | 7524 ASSERT(not_equal == 0 || not_equal == 1); |
| 7515 STATIC_CHECK(EQUAL == 0); | 7525 STATIC_CHECK(EQUAL == 0); |
| 7516 STATIC_CHECK(NOT_EQUAL == 1); | 7526 STATIC_CHECK(NOT_EQUAL == 1); |
| 7517 return Smi::FromInt(not_equal); | 7527 return Smi::FromInt(not_equal); |
| 7518 } | 7528 } |
| 7519 | 7529 |
| 7520 | 7530 |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7601 x_scaled /= 10; | 7611 x_scaled /= 10; |
| 7602 tie = GREATER; | 7612 tie = GREATER; |
| 7603 } | 7613 } |
| 7604 | 7614 |
| 7605 if (x_scaled < y_scaled) return Smi::FromInt(LESS); | 7615 if (x_scaled < y_scaled) return Smi::FromInt(LESS); |
| 7606 if (x_scaled > y_scaled) return Smi::FromInt(GREATER); | 7616 if (x_scaled > y_scaled) return Smi::FromInt(GREATER); |
| 7607 return Smi::FromInt(tie); | 7617 return Smi::FromInt(tie); |
| 7608 } | 7618 } |
| 7609 | 7619 |
| 7610 | 7620 |
| 7611 static Object* StringCharacterStreamCompare(RuntimeState* state, | 7621 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_StringCompare) { |
| 7612 String* x, | 7622 HandleScope handle_scope(isolate); |
| 7613 String* y) { | 7623 ASSERT(args.length() == 2); |
| 7614 StringCharacterStream stream_x(x, state->string_iterator_compare_x()); | 7624 |
| 7615 StringCharacterStream stream_y(y, state->string_iterator_compare_y()); | 7625 CONVERT_ARG_HANDLE_CHECKED(String, x, 0); |
| 7616 while (stream_x.HasMore() && stream_y.HasMore()) { | 7626 CONVERT_ARG_HANDLE_CHECKED(String, y, 1); |
| 7617 int d = stream_x.GetNext() - stream_y.GetNext(); | 7627 |
| 7618 if (d < 0) return Smi::FromInt(LESS); | 7628 isolate->counters()->string_compare_runtime()->Increment(); |
| 7619 else if (d > 0) return Smi::FromInt(GREATER); | 7629 |
| 7630 // A few fast case tests before we flatten. |
| 7631 if (x.is_identical_to(y)) return Smi::FromInt(EQUAL); |
| 7632 if (y->length() == 0) { |
| 7633 if (x->length() == 0) return Smi::FromInt(EQUAL); |
| 7634 return Smi::FromInt(GREATER); |
| 7635 } else if (x->length() == 0) { |
| 7636 return Smi::FromInt(LESS); |
| 7620 } | 7637 } |
| 7621 | 7638 |
| 7622 // x is (non-trivial) prefix of y: | 7639 int d = x->Get(0) - y->Get(0); |
| 7623 if (stream_y.HasMore()) return Smi::FromInt(LESS); | 7640 if (d < 0) return Smi::FromInt(LESS); |
| 7624 // y is prefix of x: | 7641 else if (d > 0) return Smi::FromInt(GREATER); |
| 7625 return Smi::FromInt(stream_x.HasMore() ? GREATER : EQUAL); | |
| 7626 } | |
| 7627 | 7642 |
| 7643 // Slow case. |
| 7644 x = String::Flatten(x); |
| 7645 y = String::Flatten(y); |
| 7628 | 7646 |
| 7629 static Object* FlatStringCompare(String* x, String* y) { | 7647 DisallowHeapAllocation no_gc; |
| 7630 ASSERT(x->IsFlat()); | |
| 7631 ASSERT(y->IsFlat()); | |
| 7632 Object* equal_prefix_result = Smi::FromInt(EQUAL); | 7648 Object* equal_prefix_result = Smi::FromInt(EQUAL); |
| 7633 int prefix_length = x->length(); | 7649 int prefix_length = x->length(); |
| 7634 if (y->length() < prefix_length) { | 7650 if (y->length() < prefix_length) { |
| 7635 prefix_length = y->length(); | 7651 prefix_length = y->length(); |
| 7636 equal_prefix_result = Smi::FromInt(GREATER); | 7652 equal_prefix_result = Smi::FromInt(GREATER); |
| 7637 } else if (y->length() > prefix_length) { | 7653 } else if (y->length() > prefix_length) { |
| 7638 equal_prefix_result = Smi::FromInt(LESS); | 7654 equal_prefix_result = Smi::FromInt(LESS); |
| 7639 } | 7655 } |
| 7640 int r; | 7656 int r; |
| 7641 DisallowHeapAllocation no_gc; | |
| 7642 String::FlatContent x_content = x->GetFlatContent(); | 7657 String::FlatContent x_content = x->GetFlatContent(); |
| 7643 String::FlatContent y_content = y->GetFlatContent(); | 7658 String::FlatContent y_content = y->GetFlatContent(); |
| 7644 if (x_content.IsAscii()) { | 7659 if (x_content.IsAscii()) { |
| 7645 Vector<const uint8_t> x_chars = x_content.ToOneByteVector(); | 7660 Vector<const uint8_t> x_chars = x_content.ToOneByteVector(); |
| 7646 if (y_content.IsAscii()) { | 7661 if (y_content.IsAscii()) { |
| 7647 Vector<const uint8_t> y_chars = y_content.ToOneByteVector(); | 7662 Vector<const uint8_t> y_chars = y_content.ToOneByteVector(); |
| 7648 r = CompareChars(x_chars.start(), y_chars.start(), prefix_length); | 7663 r = CompareChars(x_chars.start(), y_chars.start(), prefix_length); |
| 7649 } else { | 7664 } else { |
| 7650 Vector<const uc16> y_chars = y_content.ToUC16Vector(); | 7665 Vector<const uc16> y_chars = y_content.ToUC16Vector(); |
| 7651 r = CompareChars(x_chars.start(), y_chars.start(), prefix_length); | 7666 r = CompareChars(x_chars.start(), y_chars.start(), prefix_length); |
| 7652 } | 7667 } |
| 7653 } else { | 7668 } else { |
| 7654 Vector<const uc16> x_chars = x_content.ToUC16Vector(); | 7669 Vector<const uc16> x_chars = x_content.ToUC16Vector(); |
| 7655 if (y_content.IsAscii()) { | 7670 if (y_content.IsAscii()) { |
| 7656 Vector<const uint8_t> y_chars = y_content.ToOneByteVector(); | 7671 Vector<const uint8_t> y_chars = y_content.ToOneByteVector(); |
| 7657 r = CompareChars(x_chars.start(), y_chars.start(), prefix_length); | 7672 r = CompareChars(x_chars.start(), y_chars.start(), prefix_length); |
| 7658 } else { | 7673 } else { |
| 7659 Vector<const uc16> y_chars = y_content.ToUC16Vector(); | 7674 Vector<const uc16> y_chars = y_content.ToUC16Vector(); |
| 7660 r = CompareChars(x_chars.start(), y_chars.start(), prefix_length); | 7675 r = CompareChars(x_chars.start(), y_chars.start(), prefix_length); |
| 7661 } | 7676 } |
| 7662 } | 7677 } |
| 7663 Object* result; | 7678 Object* result; |
| 7664 if (r == 0) { | 7679 if (r == 0) { |
| 7665 result = equal_prefix_result; | 7680 result = equal_prefix_result; |
| 7666 } else { | 7681 } else { |
| 7667 result = (r < 0) ? Smi::FromInt(LESS) : Smi::FromInt(GREATER); | 7682 result = (r < 0) ? Smi::FromInt(LESS) : Smi::FromInt(GREATER); |
| 7668 } | 7683 } |
| 7669 ASSERT(result == | |
| 7670 StringCharacterStreamCompare(x->GetIsolate()->runtime_state(), x, y)); | |
| 7671 return result; | 7684 return result; |
| 7672 } | 7685 } |
| 7673 | 7686 |
| 7674 | 7687 |
| 7675 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_StringCompare) { | |
| 7676 HandleScope shs(isolate); | |
| 7677 ASSERT(args.length() == 2); | |
| 7678 | |
| 7679 CONVERT_ARG_CHECKED(String, x, 0); | |
| 7680 CONVERT_ARG_CHECKED(String, y, 1); | |
| 7681 | |
| 7682 isolate->counters()->string_compare_runtime()->Increment(); | |
| 7683 | |
| 7684 // A few fast case tests before we flatten. | |
| 7685 if (x == y) return Smi::FromInt(EQUAL); | |
| 7686 if (y->length() == 0) { | |
| 7687 if (x->length() == 0) return Smi::FromInt(EQUAL); | |
| 7688 return Smi::FromInt(GREATER); | |
| 7689 } else if (x->length() == 0) { | |
| 7690 return Smi::FromInt(LESS); | |
| 7691 } | |
| 7692 | |
| 7693 int d = x->Get(0) - y->Get(0); | |
| 7694 if (d < 0) return Smi::FromInt(LESS); | |
| 7695 else if (d > 0) return Smi::FromInt(GREATER); | |
| 7696 | |
| 7697 Object* obj; | |
| 7698 { MaybeObject* maybe_obj = isolate->heap()->PrepareForCompare(x); | |
| 7699 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | |
| 7700 } | |
| 7701 { MaybeObject* maybe_obj = isolate->heap()->PrepareForCompare(y); | |
| 7702 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | |
| 7703 } | |
| 7704 | |
| 7705 return (x->IsFlat() && y->IsFlat()) ? FlatStringCompare(x, y) | |
| 7706 : StringCharacterStreamCompare(isolate->runtime_state(), x, y); | |
| 7707 } | |
| 7708 | |
| 7709 | |
| 7710 #define RUNTIME_UNARY_MATH(Name, name) \ | 7688 #define RUNTIME_UNARY_MATH(Name, name) \ |
| 7711 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math##Name) { \ | 7689 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math##Name) { \ |
| 7712 SealHandleScope shs(isolate); \ | 7690 SealHandleScope shs(isolate); \ |
| 7713 ASSERT(args.length() == 1); \ | 7691 ASSERT(args.length() == 1); \ |
| 7714 isolate->counters()->math_##name()->Increment(); \ | 7692 isolate->counters()->math_##name()->Increment(); \ |
| 7715 CONVERT_DOUBLE_ARG_CHECKED(x, 0); \ | 7693 CONVERT_DOUBLE_ARG_CHECKED(x, 0); \ |
| 7716 return isolate->heap()->AllocateHeapNumber(std::name(x)); \ | 7694 return isolate->heap()->AllocateHeapNumber(std::name(x)); \ |
| 7717 } | 7695 } |
| 7718 | 7696 |
| 7719 RUNTIME_UNARY_MATH(Acos, acos) | 7697 RUNTIME_UNARY_MATH(Acos, acos) |
| (...skipping 3856 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11576 | 11554 |
| 11577 | 11555 |
| 11578 // Set the context local variable value. | 11556 // Set the context local variable value. |
| 11579 static bool SetContextLocalValue(Isolate* isolate, | 11557 static bool SetContextLocalValue(Isolate* isolate, |
| 11580 Handle<ScopeInfo> scope_info, | 11558 Handle<ScopeInfo> scope_info, |
| 11581 Handle<Context> context, | 11559 Handle<Context> context, |
| 11582 Handle<String> variable_name, | 11560 Handle<String> variable_name, |
| 11583 Handle<Object> new_value) { | 11561 Handle<Object> new_value) { |
| 11584 for (int i = 0; i < scope_info->ContextLocalCount(); i++) { | 11562 for (int i = 0; i < scope_info->ContextLocalCount(); i++) { |
| 11585 Handle<String> next_name(scope_info->ContextLocalName(i)); | 11563 Handle<String> next_name(scope_info->ContextLocalName(i)); |
| 11586 if (variable_name->Equals(*next_name)) { | 11564 if (String::Equals(variable_name, next_name)) { |
| 11587 VariableMode mode; | 11565 VariableMode mode; |
| 11588 InitializationFlag init_flag; | 11566 InitializationFlag init_flag; |
| 11589 int context_index = | 11567 int context_index = |
| 11590 scope_info->ContextSlotIndex(*next_name, &mode, &init_flag); | 11568 scope_info->ContextSlotIndex(*next_name, &mode, &init_flag); |
| 11591 context->set(context_index, *new_value); | 11569 context->set(context_index, *new_value); |
| 11592 return true; | 11570 return true; |
| 11593 } | 11571 } |
| 11594 } | 11572 } |
| 11595 | 11573 |
| 11596 return false; | 11574 return false; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 11608 } | 11586 } |
| 11609 | 11587 |
| 11610 Handle<JSFunction> function(frame->function()); | 11588 Handle<JSFunction> function(frame->function()); |
| 11611 Handle<SharedFunctionInfo> shared(function->shared()); | 11589 Handle<SharedFunctionInfo> shared(function->shared()); |
| 11612 Handle<ScopeInfo> scope_info(shared->scope_info()); | 11590 Handle<ScopeInfo> scope_info(shared->scope_info()); |
| 11613 | 11591 |
| 11614 bool default_result = false; | 11592 bool default_result = false; |
| 11615 | 11593 |
| 11616 // Parameters. | 11594 // Parameters. |
| 11617 for (int i = 0; i < scope_info->ParameterCount(); ++i) { | 11595 for (int i = 0; i < scope_info->ParameterCount(); ++i) { |
| 11618 if (scope_info->ParameterName(i)->Equals(*variable_name)) { | 11596 HandleScope scope(isolate); |
| 11597 if (String::Equals(handle(scope_info->ParameterName(i)), variable_name)) { |
| 11619 frame->SetParameterValue(i, *new_value); | 11598 frame->SetParameterValue(i, *new_value); |
| 11620 // Argument might be shadowed in heap context, don't stop here. | 11599 // Argument might be shadowed in heap context, don't stop here. |
| 11621 default_result = true; | 11600 default_result = true; |
| 11622 } | 11601 } |
| 11623 } | 11602 } |
| 11624 | 11603 |
| 11625 // Stack locals. | 11604 // Stack locals. |
| 11626 for (int i = 0; i < scope_info->StackLocalCount(); ++i) { | 11605 for (int i = 0; i < scope_info->StackLocalCount(); ++i) { |
| 11627 if (scope_info->StackLocalName(i)->Equals(*variable_name)) { | 11606 HandleScope scope(isolate); |
| 11607 if (String::Equals(handle(scope_info->StackLocalName(i)), variable_name)) { |
| 11628 frame->SetExpression(i, *new_value); | 11608 frame->SetExpression(i, *new_value); |
| 11629 return true; | 11609 return true; |
| 11630 } | 11610 } |
| 11631 } | 11611 } |
| 11632 | 11612 |
| 11633 if (scope_info->HasContext()) { | 11613 if (scope_info->HasContext()) { |
| 11634 // Context locals. | 11614 // Context locals. |
| 11635 Handle<Context> frame_context(Context::cast(frame->context())); | 11615 Handle<Context> frame_context(Context::cast(frame->context())); |
| 11636 Handle<Context> function_context(frame_context->declaration_context()); | 11616 Handle<Context> function_context(frame_context->declaration_context()); |
| 11637 if (SetContextLocalValue( | 11617 if (SetContextLocalValue( |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11758 return catch_scope; | 11738 return catch_scope; |
| 11759 } | 11739 } |
| 11760 | 11740 |
| 11761 | 11741 |
| 11762 static bool SetCatchVariableValue(Isolate* isolate, | 11742 static bool SetCatchVariableValue(Isolate* isolate, |
| 11763 Handle<Context> context, | 11743 Handle<Context> context, |
| 11764 Handle<String> variable_name, | 11744 Handle<String> variable_name, |
| 11765 Handle<Object> new_value) { | 11745 Handle<Object> new_value) { |
| 11766 ASSERT(context->IsCatchContext()); | 11746 ASSERT(context->IsCatchContext()); |
| 11767 Handle<String> name(String::cast(context->extension())); | 11747 Handle<String> name(String::cast(context->extension())); |
| 11768 if (!name->Equals(*variable_name)) { | 11748 if (!String::Equals(name, variable_name)) { |
| 11769 return false; | 11749 return false; |
| 11770 } | 11750 } |
| 11771 context->set(Context::THROWN_OBJECT_INDEX, *new_value); | 11751 context->set(Context::THROWN_OBJECT_INDEX, *new_value); |
| 11772 return true; | 11752 return true; |
| 11773 } | 11753 } |
| 11774 | 11754 |
| 11775 | 11755 |
| 11776 // Create a plain JSObject which materializes the block scope for the specified | 11756 // Create a plain JSObject which materializes the block scope for the specified |
| 11777 // block context. | 11757 // block context. |
| 11778 MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeBlockScope( | 11758 MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeBlockScope( |
| (...skipping 3443 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 15222 } | 15202 } |
| 15223 } | 15203 } |
| 15224 | 15204 |
| 15225 | 15205 |
| 15226 void Runtime::OutOfMemory() { | 15206 void Runtime::OutOfMemory() { |
| 15227 Heap::FatalProcessOutOfMemory("CALL_AND_RETRY_LAST", true); | 15207 Heap::FatalProcessOutOfMemory("CALL_AND_RETRY_LAST", true); |
| 15228 UNREACHABLE(); | 15208 UNREACHABLE(); |
| 15229 } | 15209 } |
| 15230 | 15210 |
| 15231 } } // namespace v8::internal | 15211 } } // namespace v8::internal |
| OLD | NEW |