OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 2305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2316 uint32_t shift = DoubleToInt32(y_val) & 0x1f; | 2316 uint32_t shift = DoubleToInt32(y_val) & 0x1f; |
2317 int value = ArithmeticShiftRight(DoubleToInt32(x_val), shift); | 2317 int value = ArithmeticShiftRight(DoubleToInt32(x_val), shift); |
2318 x = NewNumberLiteral(value); | 2318 x = NewNumberLiteral(value); |
2319 continue; | 2319 continue; |
2320 } | 2320 } |
2321 default: | 2321 default: |
2322 break; | 2322 break; |
2323 } | 2323 } |
2324 } | 2324 } |
2325 | 2325 |
2326 // Convert constant divisions to multiplications for speed. | |
2327 if (op == Token::DIV && | |
2328 y && y->AsLiteral() && y->AsLiteral()->handle()->IsNumber()) { | |
2329 double y_val = y->AsLiteral()->handle()->Number(); | |
2330 int64_t y_int = static_cast<int64_t>(y_val); | |
2331 // There are rounding issues with this optimization, but they don't | |
2332 // apply if the number to be divided with has a reciprocal that can be | |
2333 // precisely represented as a floating point number. This is the case | |
2334 // if the number is an integer power of 2. Negative integer powers of | |
2335 // 2 work too, but for -2, -1, 1 and 2 we don't do the strength | |
2336 // reduction because the inlined optimistic idiv has a reasonable | |
2337 // chance of succeeding by producing a Smi answer with no remainder. | |
2338 if (static_cast<double>(y_int) == y_val && | |
2339 (IsPowerOf2(y_int) || IsPowerOf2(-y_int)) && | |
2340 (y_int > 2 || y_int < -2)) { | |
2341 y = NewNumberLiteral(1 / y_val); | |
2342 op = Token::MUL; | |
2343 } | |
2344 } | |
2345 | |
2346 // For now we distinguish between comparisons and other binary | 2326 // For now we distinguish between comparisons and other binary |
2347 // operations. (We could combine the two and get rid of this | 2327 // operations. (We could combine the two and get rid of this |
2348 // code and AST node eventually.) | 2328 // code and AST node eventually.) |
2349 if (Token::IsCompareOp(op)) { | 2329 if (Token::IsCompareOp(op)) { |
2350 // We have a comparison. | 2330 // We have a comparison. |
2351 Token::Value cmp = op; | 2331 Token::Value cmp = op; |
2352 switch (op) { | 2332 switch (op) { |
2353 case Token::NE: cmp = Token::EQ; break; | 2333 case Token::NE: cmp = Token::EQ; break; |
2354 case Token::NE_STRICT: cmp = Token::EQ_STRICT; break; | 2334 case Token::NE_STRICT: cmp = Token::EQ_STRICT; break; |
2355 default: break; | 2335 default: break; |
(...skipping 1317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3673 return ReportUnexpectedToken(); | 3653 return ReportUnexpectedToken(); |
3674 } | 3654 } |
3675 Handle<String> key = GetString(); | 3655 Handle<String> key = GetString(); |
3676 if (scanner_.Next() != Token::COLON) { | 3656 if (scanner_.Next() != Token::COLON) { |
3677 return ReportUnexpectedToken(); | 3657 return ReportUnexpectedToken(); |
3678 } | 3658 } |
3679 Handle<Object> value = ParseJsonValue(); | 3659 Handle<Object> value = ParseJsonValue(); |
3680 if (value.is_null()) return Handle<Object>::null(); | 3660 if (value.is_null()) return Handle<Object>::null(); |
3681 uint32_t index; | 3661 uint32_t index; |
3682 if (key->AsArrayIndex(&index)) { | 3662 if (key->AsArrayIndex(&index)) { |
3683 CALL_HEAP_FUNCTION_INLINE( | 3663 SetOwnElement(json_object, index, value); |
3684 (*json_object)->SetElement(index, *value, true)); | |
3685 } else { | 3664 } else { |
3686 CALL_HEAP_FUNCTION_INLINE( | 3665 SetLocalPropertyIgnoreAttributes(json_object, key, value, NONE); |
3687 (*json_object)->SetPropertyPostInterceptor(*key, *value, NONE)); | |
3688 } | 3666 } |
3689 } while (scanner_.Next() == Token::COMMA); | 3667 } while (scanner_.Next() == Token::COMMA); |
3690 if (scanner_.current_token() != Token::RBRACE) { | 3668 if (scanner_.current_token() != Token::RBRACE) { |
3691 return ReportUnexpectedToken(); | 3669 return ReportUnexpectedToken(); |
3692 } | 3670 } |
3693 } | 3671 } |
3694 return json_object; | 3672 return json_object; |
3695 } | 3673 } |
3696 | 3674 |
3697 | 3675 |
(...skipping 339 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4037 break; | 4015 break; |
4038 case 't': | 4016 case 't': |
4039 Advance(2); | 4017 Advance(2); |
4040 builder->AddCharacter('\t'); | 4018 builder->AddCharacter('\t'); |
4041 break; | 4019 break; |
4042 case 'v': | 4020 case 'v': |
4043 Advance(2); | 4021 Advance(2); |
4044 builder->AddCharacter('\v'); | 4022 builder->AddCharacter('\v'); |
4045 break; | 4023 break; |
4046 case 'c': { | 4024 case 'c': { |
4047 Advance(2); | 4025 Advance(); |
4048 uc32 control = ParseControlLetterEscape(); | 4026 uc32 controlLetter = Next(); |
4049 builder->AddCharacter(control); | 4027 // Special case if it is an ASCII letter. |
| 4028 // Convert lower case letters to uppercase. |
| 4029 uc32 letter = controlLetter & ~('a' ^ 'A'); |
| 4030 if (letter < 'A' || 'Z' < letter) { |
| 4031 // controlLetter is not in range 'A'-'Z' or 'a'-'z'. |
| 4032 // This is outside the specification. We match JSC in |
| 4033 // reading the backslash as a literal character instead |
| 4034 // of as starting an escape. |
| 4035 builder->AddCharacter('\\'); |
| 4036 } else { |
| 4037 Advance(2); |
| 4038 builder->AddCharacter(controlLetter & 0x1f); |
| 4039 } |
4050 break; | 4040 break; |
4051 } | 4041 } |
4052 case 'x': { | 4042 case 'x': { |
4053 Advance(2); | 4043 Advance(2); |
4054 uc32 value; | 4044 uc32 value; |
4055 if (ParseHexEscape(2, &value)) { | 4045 if (ParseHexEscape(2, &value)) { |
4056 builder->AddCharacter(value); | 4046 builder->AddCharacter(value); |
4057 } else { | 4047 } else { |
4058 builder->AddCharacter('x'); | 4048 builder->AddCharacter('x'); |
4059 } | 4049 } |
(...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4314 } else { | 4304 } else { |
4315 Reset(start); | 4305 Reset(start); |
4316 return false; | 4306 return false; |
4317 } | 4307 } |
4318 *min_out = min; | 4308 *min_out = min; |
4319 *max_out = max; | 4309 *max_out = max; |
4320 return true; | 4310 return true; |
4321 } | 4311 } |
4322 | 4312 |
4323 | 4313 |
4324 // Upper and lower case letters differ by one bit. | |
4325 STATIC_CHECK(('a' ^ 'A') == 0x20); | |
4326 | |
4327 uc32 RegExpParser::ParseControlLetterEscape() { | |
4328 if (!has_more()) | |
4329 return 'c'; | |
4330 uc32 letter = current() & ~(0x20); // Collapse upper and lower case letters. | |
4331 if (letter < 'A' || 'Z' < letter) { | |
4332 // Non-spec error-correction: "\c" followed by non-control letter is | |
4333 // interpreted as an IdentityEscape of 'c'. | |
4334 return 'c'; | |
4335 } | |
4336 Advance(); | |
4337 return letter & 0x1f; // Remainder modulo 32, per specification. | |
4338 } | |
4339 | |
4340 | |
4341 uc32 RegExpParser::ParseOctalLiteral() { | 4314 uc32 RegExpParser::ParseOctalLiteral() { |
4342 ASSERT('0' <= current() && current() <= '7'); | 4315 ASSERT('0' <= current() && current() <= '7'); |
4343 // For compatibility with some other browsers (not all), we parse | 4316 // For compatibility with some other browsers (not all), we parse |
4344 // up to three octal digits with a value below 256. | 4317 // up to three octal digits with a value below 256. |
4345 uc32 value = current() - '0'; | 4318 uc32 value = current() - '0'; |
4346 Advance(); | 4319 Advance(); |
4347 if ('0' <= current() && current() <= '7') { | 4320 if ('0' <= current() && current() <= '7') { |
4348 value = value * 8 + current() - '0'; | 4321 value = value * 8 + current() - '0'; |
4349 Advance(); | 4322 Advance(); |
4350 if (value < 32 && '0' <= current() && current() <= '7') { | 4323 if (value < 32 && '0' <= current() && current() <= '7') { |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4396 return '\n'; | 4369 return '\n'; |
4397 case 'r': | 4370 case 'r': |
4398 Advance(); | 4371 Advance(); |
4399 return '\r'; | 4372 return '\r'; |
4400 case 't': | 4373 case 't': |
4401 Advance(); | 4374 Advance(); |
4402 return '\t'; | 4375 return '\t'; |
4403 case 'v': | 4376 case 'v': |
4404 Advance(); | 4377 Advance(); |
4405 return '\v'; | 4378 return '\v'; |
4406 case 'c': | 4379 case 'c': { |
4407 Advance(); | 4380 uc32 controlLetter = Next(); |
4408 return ParseControlLetterEscape(); | 4381 uc32 letter = controlLetter & ~('A' ^ 'a'); |
| 4382 // For compatibility with JSC, inside a character class |
| 4383 // we also accept digits and underscore as control characters. |
| 4384 if ((controlLetter >= '0' && controlLetter <= '9') || |
| 4385 controlLetter == '_' || |
| 4386 (letter >= 'A' && letter <= 'Z')) { |
| 4387 Advance(2); |
| 4388 // Control letters mapped to ASCII control characters in the range |
| 4389 // 0x00-0x1f. |
| 4390 return controlLetter & 0x1f; |
| 4391 } |
| 4392 // We match JSC in reading the backslash as a literal |
| 4393 // character instead of as starting an escape. |
| 4394 return '\\'; |
| 4395 } |
4409 case '0': case '1': case '2': case '3': case '4': case '5': | 4396 case '0': case '1': case '2': case '3': case '4': case '5': |
4410 case '6': case '7': | 4397 case '6': case '7': |
4411 // For compatibility, we interpret a decimal escape that isn't | 4398 // For compatibility, we interpret a decimal escape that isn't |
4412 // a back reference (and therefore either \0 or not valid according | 4399 // a back reference (and therefore either \0 or not valid according |
4413 // to the specification) as a 1..3 digit octal character code. | 4400 // to the specification) as a 1..3 digit octal character code. |
4414 return ParseOctalLiteral(); | 4401 return ParseOctalLiteral(); |
4415 case 'x': { | 4402 case 'x': { |
4416 Advance(); | 4403 Advance(); |
4417 uc32 value; | 4404 uc32 value; |
4418 if (ParseHexEscape(2, &value)) { | 4405 if (ParseHexEscape(2, &value)) { |
(...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4708 Handle<String> source = Handle<String>(String::cast(script->source())); | 4695 Handle<String> source = Handle<String>(String::cast(script->source())); |
4709 result = parser.ParseProgram(source, info->is_global()); | 4696 result = parser.ParseProgram(source, info->is_global()); |
4710 } | 4697 } |
4711 } | 4698 } |
4712 | 4699 |
4713 info->SetFunction(result); | 4700 info->SetFunction(result); |
4714 return (result != NULL); | 4701 return (result != NULL); |
4715 } | 4702 } |
4716 | 4703 |
4717 } } // namespace v8::internal | 4704 } } // namespace v8::internal |
OLD | NEW |