Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1065)

Side by Side Diff: src/runtime.cc

Issue 225823003: Implement handlified String::Equals and Name::Equals. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: refactored StringToDouble Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/parser.cc ('k') | src/scanner.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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 &nbsp;. 6195 // than '9' except 'I' and &nbsp;.
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/parser.cc ('k') | src/scanner.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698