| OLD | NEW |
| 1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 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 3658 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3669 case JS_FUNCTION_TYPE: case JS_REGEXP_TYPE: | 3669 case JS_FUNCTION_TYPE: case JS_REGEXP_TYPE: |
| 3670 return Heap::function_symbol(); | 3670 return Heap::function_symbol(); |
| 3671 default: | 3671 default: |
| 3672 // For any kind of object not handled above, the spec rule for | 3672 // For any kind of object not handled above, the spec rule for |
| 3673 // host objects gives that it is okay to return "object" | 3673 // host objects gives that it is okay to return "object" |
| 3674 return Heap::object_symbol(); | 3674 return Heap::object_symbol(); |
| 3675 } | 3675 } |
| 3676 } | 3676 } |
| 3677 | 3677 |
| 3678 | 3678 |
| 3679 static double StringToNumber(String* subject) { |
| 3680 subject->TryFlatten(); |
| 3681 return StringToDouble(subject, ALLOW_HEX); |
| 3682 } |
| 3683 |
| 3684 |
| 3679 static Object* Runtime_StringToNumber(Arguments args) { | 3685 static Object* Runtime_StringToNumber(Arguments args) { |
| 3680 NoHandleAllocation ha; | 3686 NoHandleAllocation ha; |
| 3681 ASSERT(args.length() == 1); | 3687 ASSERT(args.length() == 1); |
| 3682 CONVERT_CHECKED(String, subject, args[0]); | 3688 CONVERT_CHECKED(String, subject, args[0]); |
| 3683 subject->TryFlatten(); | 3689 return Heap::NumberFromDouble(StringToNumber(subject)); |
| 3684 return Heap::NumberFromDouble(StringToDouble(subject, ALLOW_HEX)); | |
| 3685 } | 3690 } |
| 3686 | 3691 |
| 3687 | 3692 |
| 3688 static Object* Runtime_StringFromCharCodeArray(Arguments args) { | 3693 static Object* Runtime_StringFromCharCodeArray(Arguments args) { |
| 3689 NoHandleAllocation ha; | 3694 NoHandleAllocation ha; |
| 3690 ASSERT(args.length() == 1); | 3695 ASSERT(args.length() == 1); |
| 3691 | 3696 |
| 3692 CONVERT_CHECKED(JSArray, codes, args[0]); | 3697 CONVERT_CHECKED(JSArray, codes, args[0]); |
| 3693 int length = Smi::cast(codes->length())->value(); | 3698 int length = Smi::cast(codes->length())->value(); |
| 3694 | 3699 |
| (...skipping 796 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4491 static Object* Runtime_NumberSar(Arguments args) { | 4496 static Object* Runtime_NumberSar(Arguments args) { |
| 4492 NoHandleAllocation ha; | 4497 NoHandleAllocation ha; |
| 4493 ASSERT(args.length() == 2); | 4498 ASSERT(args.length() == 2); |
| 4494 | 4499 |
| 4495 CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]); | 4500 CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]); |
| 4496 CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]); | 4501 CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]); |
| 4497 return Heap::NumberFromInt32(ArithmeticShiftRight(x, y & 0x1f)); | 4502 return Heap::NumberFromInt32(ArithmeticShiftRight(x, y & 0x1f)); |
| 4498 } | 4503 } |
| 4499 | 4504 |
| 4500 | 4505 |
| 4501 static Object* Runtime_NumberEquals(Arguments args) { | 4506 static Object* NumberEquals(double x, double y) { |
| 4502 NoHandleAllocation ha; | |
| 4503 ASSERT(args.length() == 2); | |
| 4504 | |
| 4505 CONVERT_DOUBLE_CHECKED(x, args[0]); | |
| 4506 CONVERT_DOUBLE_CHECKED(y, args[1]); | |
| 4507 if (isnan(x)) return Smi::FromInt(NOT_EQUAL); | 4507 if (isnan(x)) return Smi::FromInt(NOT_EQUAL); |
| 4508 if (isnan(y)) return Smi::FromInt(NOT_EQUAL); | 4508 if (isnan(y)) return Smi::FromInt(NOT_EQUAL); |
| 4509 if (x == y) return Smi::FromInt(EQUAL); | 4509 if (x == y) return Smi::FromInt(EQUAL); |
| 4510 Object* result; | 4510 Object* result; |
| 4511 if ((fpclassify(x) == FP_ZERO) && (fpclassify(y) == FP_ZERO)) { | 4511 if ((fpclassify(x) == FP_ZERO) && (fpclassify(y) == FP_ZERO)) { |
| 4512 result = Smi::FromInt(EQUAL); | 4512 result = Smi::FromInt(EQUAL); |
| 4513 } else { | 4513 } else { |
| 4514 result = Smi::FromInt(NOT_EQUAL); | 4514 result = Smi::FromInt(NOT_EQUAL); |
| 4515 } | 4515 } |
| 4516 return result; | 4516 return result; |
| 4517 } | 4517 } |
| 4518 | 4518 |
| 4519 | 4519 |
| 4520 static Object* Runtime_StringEquals(Arguments args) { | 4520 static Object* Runtime_NumberEquals(Arguments args) { |
| 4521 NoHandleAllocation ha; | 4521 NoHandleAllocation ha; |
| 4522 ASSERT(args.length() == 2); | 4522 ASSERT(args.length() == 2); |
| 4523 | 4523 |
| 4524 CONVERT_CHECKED(String, x, args[0]); | 4524 CONVERT_DOUBLE_CHECKED(x, args[0]); |
| 4525 CONVERT_CHECKED(String, y, args[1]); | 4525 CONVERT_DOUBLE_CHECKED(y, args[1]); |
| 4526 return NumberEquals(x, y); |
| 4527 } |
| 4526 | 4528 |
| 4529 |
| 4530 static Object* StringEquals(String* x, String* y) { |
| 4527 bool not_equal = !x->Equals(y); | 4531 bool not_equal = !x->Equals(y); |
| 4528 // This is slightly convoluted because the value that signifies | 4532 // This is slightly convoluted because the value that signifies |
| 4529 // equality is 0 and inequality is 1 so we have to negate the result | 4533 // equality is 0 and inequality is 1 so we have to negate the result |
| 4530 // from String::Equals. | 4534 // from String::Equals. |
| 4531 ASSERT(not_equal == 0 || not_equal == 1); | 4535 ASSERT(not_equal == 0 || not_equal == 1); |
| 4532 STATIC_CHECK(EQUAL == 0); | 4536 STATIC_CHECK(EQUAL == 0); |
| 4533 STATIC_CHECK(NOT_EQUAL == 1); | 4537 STATIC_CHECK(NOT_EQUAL == 1); |
| 4534 return Smi::FromInt(not_equal); | 4538 return Smi::FromInt(not_equal); |
| 4535 } | 4539 } |
| 4536 | 4540 |
| 4537 | 4541 |
| 4542 static Object* Runtime_StringEquals(Arguments args) { |
| 4543 NoHandleAllocation ha; |
| 4544 ASSERT(args.length() == 2); |
| 4545 |
| 4546 CONVERT_CHECKED(String, x, args[0]); |
| 4547 CONVERT_CHECKED(String, y, args[1]); |
| 4548 |
| 4549 return StringEquals(x, y); |
| 4550 } |
| 4551 |
| 4552 |
| 4538 static Object* Runtime_NumberCompare(Arguments args) { | 4553 static Object* Runtime_NumberCompare(Arguments args) { |
| 4539 NoHandleAllocation ha; | 4554 NoHandleAllocation ha; |
| 4540 ASSERT(args.length() == 3); | 4555 ASSERT(args.length() == 3); |
| 4541 | 4556 |
| 4542 CONVERT_DOUBLE_CHECKED(x, args[0]); | 4557 CONVERT_DOUBLE_CHECKED(x, args[0]); |
| 4543 CONVERT_DOUBLE_CHECKED(y, args[1]); | 4558 CONVERT_DOUBLE_CHECKED(y, args[1]); |
| 4544 if (isnan(x) || isnan(y)) return args[2]; | 4559 if (isnan(x) || isnan(y)) return args[2]; |
| 4545 if (x == y) return Smi::FromInt(EQUAL); | 4560 if (x == y) return Smi::FromInt(EQUAL); |
| 4546 if (isless(x, y)) return Smi::FromInt(LESS); | 4561 if (isless(x, y)) return Smi::FromInt(LESS); |
| 4547 return Smi::FromInt(GREATER); | 4562 return Smi::FromInt(GREATER); |
| (...skipping 3798 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8346 Logger::LogRuntime(chars, elms); | 8361 Logger::LogRuntime(chars, elms); |
| 8347 return Heap::undefined_value(); | 8362 return Heap::undefined_value(); |
| 8348 } | 8363 } |
| 8349 | 8364 |
| 8350 | 8365 |
| 8351 static Object* Runtime_IS_VAR(Arguments args) { | 8366 static Object* Runtime_IS_VAR(Arguments args) { |
| 8352 UNREACHABLE(); // implemented as macro in the parser | 8367 UNREACHABLE(); // implemented as macro in the parser |
| 8353 return NULL; | 8368 return NULL; |
| 8354 } | 8369 } |
| 8355 | 8370 |
| 8371 static inline Object* StrictObjectEquals(Object* x, Object* y) { |
| 8372 return (x == y) ? Smi::FromInt(EQUAL) : Smi::FromInt(NOT_EQUAL); |
| 8373 } |
| 8374 |
| 8375 |
| 8376 // Equivalent of JS 'x == null'. |
| 8377 static bool EqualsToNull(Object* x) { |
| 8378 return x->IsNull() || x->IsUndefined() || x->IsUndetectableObject(); |
| 8379 } |
| 8380 |
| 8381 |
| 8382 static double BooleanToNumber(Object* x) { |
| 8383 return x->IsTrue() ? 1 : 0; |
| 8384 } |
| 8385 |
| 8386 |
| 8387 static double ObjectToNumber(Object* x, bool* supported) { |
| 8388 if (x->IsNumber()) { |
| 8389 return x->Number(); |
| 8390 } else if (x->IsString()) { |
| 8391 return StringToNumber(String::cast(x)); |
| 8392 } else if (x->IsBoolean()) { |
| 8393 return BooleanToNumber(x); |
| 8394 } else if (x->IsUndefined()) { |
| 8395 return OS::nan_value(); |
| 8396 } else if (EqualsToNull(x)) { |
| 8397 return 0; |
| 8398 } else { |
| 8399 *supported = false; |
| 8400 return 0; |
| 8401 } |
| 8402 } |
| 8403 |
| 8404 |
| 8405 static Object* Runtime_FastEquals(Arguments args) { |
| 8406 // Partial implementation of the compare operations. |
| 8407 // Returns EQUAL, NOT_EQUAL or a special case code which must be handled |
| 8408 // in a builting function EQUAL (comparisons implying calling custom JS |
| 8409 // code difficult to handle in C). |
| 8410 |
| 8411 const int EQUALS_FIRST_ARG_TO_PRIMITIVE = 2; |
| 8412 const int EQUALS_SECOND_ARG_TO_PRIMITIVE = 3; |
| 8413 const int EQUALS_SECOND_ARG_TO_DEFAULT_VALUE = 4; |
| 8414 |
| 8415 NoHandleAllocation ha; |
| 8416 AssertNoAllocation na(); |
| 8417 Object* x = args[0]; |
| 8418 Object* y = args[1]; |
| 8419 |
| 8420 if (EqualsToNull(x)) { |
| 8421 // NOTE: This checks for null, undefined and undetactable. |
| 8422 // Undetactable check must be before string check. |
| 8423 return EqualsToNull(y) ? Smi::FromInt(EQUAL) : Smi::FromInt(NOT_EQUAL); |
| 8424 } else if (x->IsString()) { |
| 8425 if (y->IsString()) return StringEquals(String::cast(x), String::cast(y)); |
| 8426 if (y->IsNumber()) { |
| 8427 double dx = StringToNumber(String::cast(x)); // Type checked above. |
| 8428 return NumberEquals(dx, y->Number()); |
| 8429 } |
| 8430 if (y->IsBoolean()) { |
| 8431 double dx = StringToNumber(String::cast(x)); // Type checked above. |
| 8432 double dy = BooleanToNumber(y); |
| 8433 return NumberEquals(dx, dy); |
| 8434 } |
| 8435 if (EqualsToNull(y)) { |
| 8436 return Smi::FromInt(NOT_EQUAL); |
| 8437 } |
| 8438 |
| 8439 // Speclal case: y = %ToPrimitive(y, NO_HINT) and repeat. |
| 8440 return Smi::FromInt(EQUALS_SECOND_ARG_TO_PRIMITIVE); |
| 8441 } else if (x->IsNumber()) { |
| 8442 if (EqualsToNull(y)) return Smi::FromInt(NOT_EQUAL); |
| 8443 bool supported = true; |
| 8444 double dy = ObjectToNumber(y, &supported); // y is not null. |
| 8445 if (!supported) return Smi::FromInt(EQUALS_SECOND_ARG_TO_DEFAULT_VALUE); |
| 8446 return NumberEquals(x->Number(), dy); |
| 8447 } else if (x->IsBoolean()) { |
| 8448 if (y->IsBoolean()) { |
| 8449 return StrictObjectEquals(x, y); |
| 8450 } |
| 8451 if (EqualsToNull(y)) return Smi::FromInt(NOT_EQUAL); |
| 8452 double dx = BooleanToNumber(x); // Type checked above. |
| 8453 bool supported = true; |
| 8454 double dy = ObjectToNumber(y, &supported); |
| 8455 if (!supported) return Smi::FromInt(EQUALS_SECOND_ARG_TO_DEFAULT_VALUE); |
| 8456 return NumberEquals(dx, dy); |
| 8457 } else { |
| 8458 // x is not a number, boolean, null or undefined. |
| 8459 if (EqualsToNull(y)) return Smi::FromInt(NOT_EQUAL); |
| 8460 if (y->IsJSObject()) { |
| 8461 return StrictObjectEquals(x, y); |
| 8462 } |
| 8463 if (y->IsJSFunction()) { |
| 8464 return StrictObjectEquals(x, y); |
| 8465 } |
| 8466 |
| 8467 // Speclal case: x = %ToPrimitive(x, NO_HINT) and repeat. |
| 8468 return Smi::FromInt(EQUALS_FIRST_ARG_TO_PRIMITIVE); |
| 8469 } |
| 8470 } |
| 8471 |
| 8356 | 8472 |
| 8357 // ---------------------------------------------------------------------------- | 8473 // ---------------------------------------------------------------------------- |
| 8358 // Implementation of Runtime | 8474 // Implementation of Runtime |
| 8359 | 8475 |
| 8360 #define F(name, nargs, ressize) \ | 8476 #define F(name, nargs, ressize) \ |
| 8361 { #name, FUNCTION_ADDR(Runtime_##name), nargs, \ | 8477 { #name, FUNCTION_ADDR(Runtime_##name), nargs, \ |
| 8362 static_cast<int>(Runtime::k##name), ressize }, | 8478 static_cast<int>(Runtime::k##name), ressize }, |
| 8363 | 8479 |
| 8364 static Runtime::Function Runtime_functions[] = { | 8480 static Runtime::Function Runtime_functions[] = { |
| 8365 RUNTIME_FUNCTION_LIST(F) | 8481 RUNTIME_FUNCTION_LIST(F) |
| (...skipping 28 matching lines...) Expand all Loading... |
| 8394 } else { | 8510 } else { |
| 8395 // Handle last resort GC and make sure to allow future allocations | 8511 // Handle last resort GC and make sure to allow future allocations |
| 8396 // to grow the heap without causing GCs (if possible). | 8512 // to grow the heap without causing GCs (if possible). |
| 8397 Counters::gc_last_resort_from_js.Increment(); | 8513 Counters::gc_last_resort_from_js.Increment(); |
| 8398 Heap::CollectAllGarbage(false); | 8514 Heap::CollectAllGarbage(false); |
| 8399 } | 8515 } |
| 8400 } | 8516 } |
| 8401 | 8517 |
| 8402 | 8518 |
| 8403 } } // namespace v8::internal | 8519 } } // namespace v8::internal |
| OLD | NEW |