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 double value; |
| 6232 |
| 6233 { DisallowHeapAllocation no_gc; |
| 6234 String::FlatContent flat = subject->GetFlatContent(); |
| 6235 |
| 6236 // ECMA-262 section 15.1.2.3, empty string is NaN |
| 6237 if (flat.IsAscii()) { |
| 6238 value = StringToDouble( |
| 6239 isolate->unicode_cache(), flat.ToOneByteVector(), flags); |
| 6240 } else { |
| 6241 value = StringToDouble( |
| 6242 isolate->unicode_cache(), flat.ToUC16Vector(), flags); |
| 6243 } |
| 6244 } |
| 6245 |
| 6246 return *isolate->factory()->NewNumber(value); |
6234 } | 6247 } |
6235 | 6248 |
6236 | 6249 |
6237 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewString) { | 6250 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewString) { |
6238 SealHandleScope shs(isolate); | 6251 SealHandleScope shs(isolate); |
6239 CONVERT_SMI_ARG_CHECKED(length, 0); | 6252 CONVERT_SMI_ARG_CHECKED(length, 0); |
6240 CONVERT_BOOLEAN_ARG_CHECKED(is_one_byte, 1); | 6253 CONVERT_BOOLEAN_ARG_CHECKED(is_one_byte, 1); |
6241 if (length == 0) return isolate->heap()->empty_string(); | 6254 if (length == 0) return isolate->heap()->empty_string(); |
6242 if (is_one_byte) { | 6255 if (is_one_byte) { |
6243 return isolate->heap()->AllocateRawOneByteString(length); | 6256 return isolate->heap()->AllocateRawOneByteString(length); |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6297 | 6310 |
6298 RUNTIME_FUNCTION(MaybeObject*, Runtime_BasicJSONStringify) { | 6311 RUNTIME_FUNCTION(MaybeObject*, Runtime_BasicJSONStringify) { |
6299 HandleScope scope(isolate); | 6312 HandleScope scope(isolate); |
6300 ASSERT(args.length() == 1); | 6313 ASSERT(args.length() == 1); |
6301 BasicJsonStringifier stringifier(isolate); | 6314 BasicJsonStringifier stringifier(isolate); |
6302 return stringifier.Stringify(Handle<Object>(args[0], isolate)); | 6315 return stringifier.Stringify(Handle<Object>(args[0], isolate)); |
6303 } | 6316 } |
6304 | 6317 |
6305 | 6318 |
6306 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringParseInt) { | 6319 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringParseInt) { |
6307 SealHandleScope shs(isolate); | 6320 HandleScope handle_scope(isolate); |
| 6321 CONVERT_ARG_HANDLE_CHECKED(String, subject, 0); |
| 6322 CONVERT_SMI_ARG_CHECKED(radix, 1); |
| 6323 RUNTIME_ASSERT(radix == 0 || (2 <= radix && radix <= 36)); |
6308 | 6324 |
6309 CONVERT_ARG_CHECKED(String, s, 0); | 6325 subject = String::Flatten(subject); |
6310 CONVERT_SMI_ARG_CHECKED(radix, 1); | 6326 double value; |
6311 | 6327 |
6312 s->TryFlatten(); | 6328 { DisallowHeapAllocation no_gc; |
| 6329 String::FlatContent flat = subject->GetFlatContent(); |
6313 | 6330 |
6314 RUNTIME_ASSERT(radix == 0 || (2 <= radix && radix <= 36)); | 6331 // ECMA-262 section 15.1.2.3, empty string is NaN |
6315 double value = StringToInt(isolate->unicode_cache(), s, radix); | 6332 if (flat.IsAscii()) { |
6316 return isolate->heap()->NumberFromDouble(value); | 6333 value = StringToInt( |
| 6334 isolate->unicode_cache(), flat.ToOneByteVector(), radix); |
| 6335 } else { |
| 6336 value = StringToInt( |
| 6337 isolate->unicode_cache(), flat.ToUC16Vector(), radix); |
| 6338 } |
| 6339 } |
| 6340 |
| 6341 return *isolate->factory()->NewNumber(value); |
6317 } | 6342 } |
6318 | 6343 |
6319 | 6344 |
6320 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringParseFloat) { | 6345 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringParseFloat) { |
6321 SealHandleScope shs(isolate); | 6346 HandleScope shs(isolate); |
6322 CONVERT_ARG_CHECKED(String, str, 0); | 6347 CONVERT_ARG_HANDLE_CHECKED(String, subject, 0); |
6323 | 6348 |
6324 // ECMA-262 section 15.1.2.3, empty string is NaN | 6349 subject = String::Flatten(subject); |
6325 double value = StringToDouble(isolate->unicode_cache(), | 6350 double value; |
6326 str, ALLOW_TRAILING_JUNK, OS::nan_value()); | |
6327 | 6351 |
6328 // Create a number object from the value. | 6352 { DisallowHeapAllocation no_gc; |
6329 return isolate->heap()->NumberFromDouble(value); | 6353 String::FlatContent flat = subject->GetFlatContent(); |
| 6354 |
| 6355 // ECMA-262 section 15.1.2.3, empty string is NaN |
| 6356 if (flat.IsAscii()) { |
| 6357 value = StringToDouble(isolate->unicode_cache(), |
| 6358 flat.ToOneByteVector(), |
| 6359 ALLOW_TRAILING_JUNK, |
| 6360 OS::nan_value()); |
| 6361 } else { |
| 6362 ASSERT(flat.IsTwoByte()); |
| 6363 value = StringToDouble(isolate->unicode_cache(), |
| 6364 flat.ToUC16Vector(), |
| 6365 ALLOW_TRAILING_JUNK, |
| 6366 OS::nan_value()); |
| 6367 } |
| 6368 } |
| 6369 |
| 6370 return *isolate->factory()->NewNumber(value); |
6330 } | 6371 } |
6331 | 6372 |
6332 | 6373 |
6333 static inline bool ToUpperOverflows(uc32 character) { | 6374 static inline bool ToUpperOverflows(uc32 character) { |
6334 // y with umlauts and the micro sign are the only characters that stop | 6375 // y with umlauts and the micro sign are the only characters that stop |
6335 // fitting into one-byte when converting to uppercase. | 6376 // fitting into one-byte when converting to uppercase. |
6336 static const uc32 yuml_code = 0xff; | 6377 static const uc32 yuml_code = 0xff; |
6337 static const uc32 micro_code = 0xb5; | 6378 static const uc32 micro_code = 0xb5; |
6338 return (character == yuml_code || character == micro_code); | 6379 return (character == yuml_code || character == micro_code); |
6339 } | 6380 } |
(...skipping 1154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7494 if ((fpclassify(x) == FP_ZERO) && (fpclassify(y) == FP_ZERO)) { | 7535 if ((fpclassify(x) == FP_ZERO) && (fpclassify(y) == FP_ZERO)) { |
7495 result = Smi::FromInt(EQUAL); | 7536 result = Smi::FromInt(EQUAL); |
7496 } else { | 7537 } else { |
7497 result = Smi::FromInt(NOT_EQUAL); | 7538 result = Smi::FromInt(NOT_EQUAL); |
7498 } | 7539 } |
7499 return result; | 7540 return result; |
7500 } | 7541 } |
7501 | 7542 |
7502 | 7543 |
7503 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringEquals) { | 7544 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringEquals) { |
7504 SealHandleScope shs(isolate); | 7545 HandleScope handle_scope(isolate); |
7505 ASSERT(args.length() == 2); | 7546 ASSERT(args.length() == 2); |
7506 | 7547 |
7507 CONVERT_ARG_CHECKED(String, x, 0); | 7548 CONVERT_ARG_HANDLE_CHECKED(String, x, 0); |
7508 CONVERT_ARG_CHECKED(String, y, 1); | 7549 CONVERT_ARG_HANDLE_CHECKED(String, y, 1); |
7509 | 7550 |
7510 bool not_equal = !x->Equals(y); | 7551 bool not_equal = !String::Equals(x, y); |
7511 // This is slightly convoluted because the value that signifies | 7552 // This is slightly convoluted because the value that signifies |
7512 // equality is 0 and inequality is 1 so we have to negate the result | 7553 // equality is 0 and inequality is 1 so we have to negate the result |
7513 // from String::Equals. | 7554 // from String::Equals. |
7514 ASSERT(not_equal == 0 || not_equal == 1); | 7555 ASSERT(not_equal == 0 || not_equal == 1); |
7515 STATIC_CHECK(EQUAL == 0); | 7556 STATIC_CHECK(EQUAL == 0); |
7516 STATIC_CHECK(NOT_EQUAL == 1); | 7557 STATIC_CHECK(NOT_EQUAL == 1); |
7517 return Smi::FromInt(not_equal); | 7558 return Smi::FromInt(not_equal); |
7518 } | 7559 } |
7519 | 7560 |
7520 | 7561 |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7601 x_scaled /= 10; | 7642 x_scaled /= 10; |
7602 tie = GREATER; | 7643 tie = GREATER; |
7603 } | 7644 } |
7604 | 7645 |
7605 if (x_scaled < y_scaled) return Smi::FromInt(LESS); | 7646 if (x_scaled < y_scaled) return Smi::FromInt(LESS); |
7606 if (x_scaled > y_scaled) return Smi::FromInt(GREATER); | 7647 if (x_scaled > y_scaled) return Smi::FromInt(GREATER); |
7607 return Smi::FromInt(tie); | 7648 return Smi::FromInt(tie); |
7608 } | 7649 } |
7609 | 7650 |
7610 | 7651 |
7611 static Object* StringCharacterStreamCompare(RuntimeState* state, | 7652 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_StringCompare) { |
7612 String* x, | 7653 HandleScope handle_scope(isolate); |
7613 String* y) { | 7654 ASSERT(args.length() == 2); |
7614 StringCharacterStream stream_x(x, state->string_iterator_compare_x()); | 7655 |
7615 StringCharacterStream stream_y(y, state->string_iterator_compare_y()); | 7656 CONVERT_ARG_HANDLE_CHECKED(String, x, 0); |
7616 while (stream_x.HasMore() && stream_y.HasMore()) { | 7657 CONVERT_ARG_HANDLE_CHECKED(String, y, 1); |
7617 int d = stream_x.GetNext() - stream_y.GetNext(); | 7658 |
7618 if (d < 0) return Smi::FromInt(LESS); | 7659 isolate->counters()->string_compare_runtime()->Increment(); |
7619 else if (d > 0) return Smi::FromInt(GREATER); | 7660 |
| 7661 // A few fast case tests before we flatten. |
| 7662 if (x.is_identical_to(y)) return Smi::FromInt(EQUAL); |
| 7663 if (y->length() == 0) { |
| 7664 if (x->length() == 0) return Smi::FromInt(EQUAL); |
| 7665 return Smi::FromInt(GREATER); |
| 7666 } else if (x->length() == 0) { |
| 7667 return Smi::FromInt(LESS); |
7620 } | 7668 } |
7621 | 7669 |
7622 // x is (non-trivial) prefix of y: | 7670 int d = x->Get(0) - y->Get(0); |
7623 if (stream_y.HasMore()) return Smi::FromInt(LESS); | 7671 if (d < 0) return Smi::FromInt(LESS); |
7624 // y is prefix of x: | 7672 else if (d > 0) return Smi::FromInt(GREATER); |
7625 return Smi::FromInt(stream_x.HasMore() ? GREATER : EQUAL); | |
7626 } | |
7627 | 7673 |
| 7674 // Slow case. |
| 7675 x = String::Flatten(x); |
| 7676 y = String::Flatten(y); |
7628 | 7677 |
7629 static Object* FlatStringCompare(String* x, String* y) { | 7678 DisallowHeapAllocation no_gc; |
7630 ASSERT(x->IsFlat()); | |
7631 ASSERT(y->IsFlat()); | |
7632 Object* equal_prefix_result = Smi::FromInt(EQUAL); | 7679 Object* equal_prefix_result = Smi::FromInt(EQUAL); |
7633 int prefix_length = x->length(); | 7680 int prefix_length = x->length(); |
7634 if (y->length() < prefix_length) { | 7681 if (y->length() < prefix_length) { |
7635 prefix_length = y->length(); | 7682 prefix_length = y->length(); |
7636 equal_prefix_result = Smi::FromInt(GREATER); | 7683 equal_prefix_result = Smi::FromInt(GREATER); |
7637 } else if (y->length() > prefix_length) { | 7684 } else if (y->length() > prefix_length) { |
7638 equal_prefix_result = Smi::FromInt(LESS); | 7685 equal_prefix_result = Smi::FromInt(LESS); |
7639 } | 7686 } |
7640 int r; | 7687 int r; |
7641 DisallowHeapAllocation no_gc; | |
7642 String::FlatContent x_content = x->GetFlatContent(); | 7688 String::FlatContent x_content = x->GetFlatContent(); |
7643 String::FlatContent y_content = y->GetFlatContent(); | 7689 String::FlatContent y_content = y->GetFlatContent(); |
7644 if (x_content.IsAscii()) { | 7690 if (x_content.IsAscii()) { |
7645 Vector<const uint8_t> x_chars = x_content.ToOneByteVector(); | 7691 Vector<const uint8_t> x_chars = x_content.ToOneByteVector(); |
7646 if (y_content.IsAscii()) { | 7692 if (y_content.IsAscii()) { |
7647 Vector<const uint8_t> y_chars = y_content.ToOneByteVector(); | 7693 Vector<const uint8_t> y_chars = y_content.ToOneByteVector(); |
7648 r = CompareChars(x_chars.start(), y_chars.start(), prefix_length); | 7694 r = CompareChars(x_chars.start(), y_chars.start(), prefix_length); |
7649 } else { | 7695 } else { |
7650 Vector<const uc16> y_chars = y_content.ToUC16Vector(); | 7696 Vector<const uc16> y_chars = y_content.ToUC16Vector(); |
7651 r = CompareChars(x_chars.start(), y_chars.start(), prefix_length); | 7697 r = CompareChars(x_chars.start(), y_chars.start(), prefix_length); |
7652 } | 7698 } |
7653 } else { | 7699 } else { |
7654 Vector<const uc16> x_chars = x_content.ToUC16Vector(); | 7700 Vector<const uc16> x_chars = x_content.ToUC16Vector(); |
7655 if (y_content.IsAscii()) { | 7701 if (y_content.IsAscii()) { |
7656 Vector<const uint8_t> y_chars = y_content.ToOneByteVector(); | 7702 Vector<const uint8_t> y_chars = y_content.ToOneByteVector(); |
7657 r = CompareChars(x_chars.start(), y_chars.start(), prefix_length); | 7703 r = CompareChars(x_chars.start(), y_chars.start(), prefix_length); |
7658 } else { | 7704 } else { |
7659 Vector<const uc16> y_chars = y_content.ToUC16Vector(); | 7705 Vector<const uc16> y_chars = y_content.ToUC16Vector(); |
7660 r = CompareChars(x_chars.start(), y_chars.start(), prefix_length); | 7706 r = CompareChars(x_chars.start(), y_chars.start(), prefix_length); |
7661 } | 7707 } |
7662 } | 7708 } |
7663 Object* result; | 7709 Object* result; |
7664 if (r == 0) { | 7710 if (r == 0) { |
7665 result = equal_prefix_result; | 7711 result = equal_prefix_result; |
7666 } else { | 7712 } else { |
7667 result = (r < 0) ? Smi::FromInt(LESS) : Smi::FromInt(GREATER); | 7713 result = (r < 0) ? Smi::FromInt(LESS) : Smi::FromInt(GREATER); |
7668 } | 7714 } |
7669 ASSERT(result == | |
7670 StringCharacterStreamCompare(x->GetIsolate()->runtime_state(), x, y)); | |
7671 return result; | 7715 return result; |
7672 } | 7716 } |
7673 | 7717 |
7674 | 7718 |
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) \ | 7719 #define RUNTIME_UNARY_MATH(Name, name) \ |
7711 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math##Name) { \ | 7720 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math##Name) { \ |
7712 SealHandleScope shs(isolate); \ | 7721 SealHandleScope shs(isolate); \ |
7713 ASSERT(args.length() == 1); \ | 7722 ASSERT(args.length() == 1); \ |
7714 isolate->counters()->math_##name()->Increment(); \ | 7723 isolate->counters()->math_##name()->Increment(); \ |
7715 CONVERT_DOUBLE_ARG_CHECKED(x, 0); \ | 7724 CONVERT_DOUBLE_ARG_CHECKED(x, 0); \ |
7716 return isolate->heap()->AllocateHeapNumber(std::name(x)); \ | 7725 return isolate->heap()->AllocateHeapNumber(std::name(x)); \ |
7717 } | 7726 } |
7718 | 7727 |
7719 RUNTIME_UNARY_MATH(Acos, acos) | 7728 RUNTIME_UNARY_MATH(Acos, acos) |
(...skipping 3856 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11576 | 11585 |
11577 | 11586 |
11578 // Set the context local variable value. | 11587 // Set the context local variable value. |
11579 static bool SetContextLocalValue(Isolate* isolate, | 11588 static bool SetContextLocalValue(Isolate* isolate, |
11580 Handle<ScopeInfo> scope_info, | 11589 Handle<ScopeInfo> scope_info, |
11581 Handle<Context> context, | 11590 Handle<Context> context, |
11582 Handle<String> variable_name, | 11591 Handle<String> variable_name, |
11583 Handle<Object> new_value) { | 11592 Handle<Object> new_value) { |
11584 for (int i = 0; i < scope_info->ContextLocalCount(); i++) { | 11593 for (int i = 0; i < scope_info->ContextLocalCount(); i++) { |
11585 Handle<String> next_name(scope_info->ContextLocalName(i)); | 11594 Handle<String> next_name(scope_info->ContextLocalName(i)); |
11586 if (variable_name->Equals(*next_name)) { | 11595 if (String::Equals(variable_name, next_name)) { |
11587 VariableMode mode; | 11596 VariableMode mode; |
11588 InitializationFlag init_flag; | 11597 InitializationFlag init_flag; |
11589 int context_index = | 11598 int context_index = |
11590 scope_info->ContextSlotIndex(*next_name, &mode, &init_flag); | 11599 scope_info->ContextSlotIndex(*next_name, &mode, &init_flag); |
11591 context->set(context_index, *new_value); | 11600 context->set(context_index, *new_value); |
11592 return true; | 11601 return true; |
11593 } | 11602 } |
11594 } | 11603 } |
11595 | 11604 |
11596 return false; | 11605 return false; |
(...skipping 11 matching lines...) Expand all Loading... |
11608 } | 11617 } |
11609 | 11618 |
11610 Handle<JSFunction> function(frame->function()); | 11619 Handle<JSFunction> function(frame->function()); |
11611 Handle<SharedFunctionInfo> shared(function->shared()); | 11620 Handle<SharedFunctionInfo> shared(function->shared()); |
11612 Handle<ScopeInfo> scope_info(shared->scope_info()); | 11621 Handle<ScopeInfo> scope_info(shared->scope_info()); |
11613 | 11622 |
11614 bool default_result = false; | 11623 bool default_result = false; |
11615 | 11624 |
11616 // Parameters. | 11625 // Parameters. |
11617 for (int i = 0; i < scope_info->ParameterCount(); ++i) { | 11626 for (int i = 0; i < scope_info->ParameterCount(); ++i) { |
11618 if (scope_info->ParameterName(i)->Equals(*variable_name)) { | 11627 HandleScope scope(isolate); |
| 11628 if (String::Equals(handle(scope_info->ParameterName(i)), variable_name)) { |
11619 frame->SetParameterValue(i, *new_value); | 11629 frame->SetParameterValue(i, *new_value); |
11620 // Argument might be shadowed in heap context, don't stop here. | 11630 // Argument might be shadowed in heap context, don't stop here. |
11621 default_result = true; | 11631 default_result = true; |
11622 } | 11632 } |
11623 } | 11633 } |
11624 | 11634 |
11625 // Stack locals. | 11635 // Stack locals. |
11626 for (int i = 0; i < scope_info->StackLocalCount(); ++i) { | 11636 for (int i = 0; i < scope_info->StackLocalCount(); ++i) { |
11627 if (scope_info->StackLocalName(i)->Equals(*variable_name)) { | 11637 HandleScope scope(isolate); |
| 11638 if (String::Equals(handle(scope_info->StackLocalName(i)), variable_name)) { |
11628 frame->SetExpression(i, *new_value); | 11639 frame->SetExpression(i, *new_value); |
11629 return true; | 11640 return true; |
11630 } | 11641 } |
11631 } | 11642 } |
11632 | 11643 |
11633 if (scope_info->HasContext()) { | 11644 if (scope_info->HasContext()) { |
11634 // Context locals. | 11645 // Context locals. |
11635 Handle<Context> frame_context(Context::cast(frame->context())); | 11646 Handle<Context> frame_context(Context::cast(frame->context())); |
11636 Handle<Context> function_context(frame_context->declaration_context()); | 11647 Handle<Context> function_context(frame_context->declaration_context()); |
11637 if (SetContextLocalValue( | 11648 if (SetContextLocalValue( |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11758 return catch_scope; | 11769 return catch_scope; |
11759 } | 11770 } |
11760 | 11771 |
11761 | 11772 |
11762 static bool SetCatchVariableValue(Isolate* isolate, | 11773 static bool SetCatchVariableValue(Isolate* isolate, |
11763 Handle<Context> context, | 11774 Handle<Context> context, |
11764 Handle<String> variable_name, | 11775 Handle<String> variable_name, |
11765 Handle<Object> new_value) { | 11776 Handle<Object> new_value) { |
11766 ASSERT(context->IsCatchContext()); | 11777 ASSERT(context->IsCatchContext()); |
11767 Handle<String> name(String::cast(context->extension())); | 11778 Handle<String> name(String::cast(context->extension())); |
11768 if (!name->Equals(*variable_name)) { | 11779 if (!String::Equals(name, variable_name)) { |
11769 return false; | 11780 return false; |
11770 } | 11781 } |
11771 context->set(Context::THROWN_OBJECT_INDEX, *new_value); | 11782 context->set(Context::THROWN_OBJECT_INDEX, *new_value); |
11772 return true; | 11783 return true; |
11773 } | 11784 } |
11774 | 11785 |
11775 | 11786 |
11776 // Create a plain JSObject which materializes the block scope for the specified | 11787 // Create a plain JSObject which materializes the block scope for the specified |
11777 // block context. | 11788 // block context. |
11778 MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeBlockScope( | 11789 MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeBlockScope( |
(...skipping 3443 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
15222 } | 15233 } |
15223 } | 15234 } |
15224 | 15235 |
15225 | 15236 |
15226 void Runtime::OutOfMemory() { | 15237 void Runtime::OutOfMemory() { |
15227 Heap::FatalProcessOutOfMemory("CALL_AND_RETRY_LAST", true); | 15238 Heap::FatalProcessOutOfMemory("CALL_AND_RETRY_LAST", true); |
15228 UNREACHABLE(); | 15239 UNREACHABLE(); |
15229 } | 15240 } |
15230 | 15241 |
15231 } } // namespace v8::internal | 15242 } } // namespace v8::internal |
OLD | NEW |