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 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
42 #include "platform.h" | 42 #include "platform.h" |
43 #include "runtime.h" | 43 #include "runtime.h" |
44 #include "scopeinfo.h" | 44 #include "scopeinfo.h" |
45 #include "smart-pointer.h" | 45 #include "smart-pointer.h" |
46 #include "stub-cache.h" | 46 #include "stub-cache.h" |
47 #include "v8threads.h" | 47 #include "v8threads.h" |
48 | 48 |
49 namespace v8 { | 49 namespace v8 { |
50 namespace internal { | 50 namespace internal { |
51 | 51 |
| 52 #if defined(V8_TARGET_ARCH_X64) || defined(V8_TARGET_ARCH_IA32) |
| 53 #define DIRECT_CALL_SUPPORTED |
| 54 #endif |
52 | 55 |
53 #define RUNTIME_ASSERT(value) \ | 56 #define RUNTIME_ASSERT(value) \ |
54 if (!(value)) return Top::ThrowIllegalOperation(); | 57 if (!(value)) return Top::ThrowIllegalOperation(); |
55 | 58 |
56 // Cast the given object to a value of the specified type and store | 59 // Cast the given object to a value of the specified type and store |
57 // it in a variable with the given name. If the object is not of the | 60 // it in a variable with the given name. If the object is not of the |
58 // expected type call IllegalOperation and return. | 61 // expected type call IllegalOperation and return. |
59 #define CONVERT_CHECKED(Type, name, obj) \ | 62 #define CONVERT_CHECKED(Type, name, obj) \ |
60 RUNTIME_ASSERT(obj->Is##Type()); \ | 63 RUNTIME_ASSERT(obj->Is##Type()); \ |
61 Type* name = Type::cast(obj); | 64 Type* name = Type::cast(obj); |
(...skipping 418 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
480 Top::context()->global_context()->context_extension_function(); | 483 Top::context()->global_context()->context_extension_function(); |
481 Object* object = Heap::AllocateJSObject(constructor); | 484 Object* object = Heap::AllocateJSObject(constructor); |
482 if (object->IsFailure()) return object; | 485 if (object->IsFailure()) return object; |
483 // Assign the exception value to the catch variable and make sure | 486 // Assign the exception value to the catch variable and make sure |
484 // that the catch variable is DontDelete. | 487 // that the catch variable is DontDelete. |
485 value = JSObject::cast(object)->SetProperty(key, value, DONT_DELETE); | 488 value = JSObject::cast(object)->SetProperty(key, value, DONT_DELETE); |
486 if (value->IsFailure()) return value; | 489 if (value->IsFailure()) return value; |
487 return object; | 490 return object; |
488 } | 491 } |
489 | 492 |
490 | 493 #ifdef DIRECT_CALL_SUPPORTED |
| 494 static Object* Runtime_ClassOf(Object* obj) { |
| 495 AssertNoAllocation na; |
| 496 #else |
491 static Object* Runtime_ClassOf(Arguments args) { | 497 static Object* Runtime_ClassOf(Arguments args) { |
492 NoHandleAllocation ha; | 498 NoHandleAllocation ha; |
493 ASSERT(args.length() == 1); | 499 ASSERT(args.length() == 1); |
494 Object* obj = args[0]; | 500 Object* obj = args[0]; |
| 501 #endif |
495 if (!obj->IsJSObject()) return Heap::null_value(); | 502 if (!obj->IsJSObject()) return Heap::null_value(); |
496 return JSObject::cast(obj)->class_name(); | 503 return JSObject::cast(obj)->class_name(); |
497 } | 504 } |
498 | 505 |
499 | 506 |
| 507 #ifdef DIRECT_CALL_SUPPORTED |
| 508 static Object* Runtime_IsInPrototypeChain(Object* O, Object* V) { |
| 509 AssertNoAllocation na; |
| 510 #else |
500 static Object* Runtime_IsInPrototypeChain(Arguments args) { | 511 static Object* Runtime_IsInPrototypeChain(Arguments args) { |
501 NoHandleAllocation ha; | 512 NoHandleAllocation ha; |
502 ASSERT(args.length() == 2); | 513 ASSERT(args.length() == 2); |
503 // See ECMA-262, section 15.3.5.3, page 88 (steps 5 - 8). | |
504 Object* O = args[0]; | 514 Object* O = args[0]; |
505 Object* V = args[1]; | 515 Object* V = args[1]; |
| 516 #endif |
| 517 // See ECMA-262, section 15.3.5.3, page 88 (steps 5 - 8). |
506 while (true) { | 518 while (true) { |
507 Object* prototype = V->GetPrototype(); | 519 Object* prototype = V->GetPrototype(); |
508 if (prototype->IsNull()) return Heap::false_value(); | 520 if (prototype->IsNull()) return Heap::false_value(); |
509 if (O == prototype) return Heap::true_value(); | 521 if (O == prototype) return Heap::true_value(); |
510 V = prototype; | 522 V = prototype; |
511 } | 523 } |
512 } | 524 } |
513 | 525 |
514 | 526 |
515 // Inserts an object as the hidden prototype of another object. | 527 // Inserts an object as the hidden prototype of another object. |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
617 elms->set(1, result.GetLazyValue()); | 629 elms->set(1, result.GetLazyValue()); |
618 elms->set(2, Heap::ToBoolean(!result.IsReadOnly())); | 630 elms->set(2, Heap::ToBoolean(!result.IsReadOnly())); |
619 } | 631 } |
620 | 632 |
621 elms->set(3, Heap::ToBoolean(!result.IsDontEnum())); | 633 elms->set(3, Heap::ToBoolean(!result.IsDontEnum())); |
622 elms->set(4, Heap::ToBoolean(!result.IsDontDelete())); | 634 elms->set(4, Heap::ToBoolean(!result.IsDontDelete())); |
623 return *desc; | 635 return *desc; |
624 } | 636 } |
625 | 637 |
626 | 638 |
| 639 #ifdef DIRECT_CALL_SUPPORTED |
| 640 static Object* Runtime_IsExtensible(Object* arg) { |
| 641 AssertNoAllocation na; |
| 642 ASSERT(arg->IsJSObject()); |
| 643 JSObject* obj = JSObject::cast(arg); |
| 644 #else |
627 static Object* Runtime_IsExtensible(Arguments args) { | 645 static Object* Runtime_IsExtensible(Arguments args) { |
628 ASSERT(args.length() == 1); | 646 ASSERT(args.length() == 1); |
629 CONVERT_CHECKED(JSObject, obj, args[0]); | 647 CONVERT_CHECKED(JSObject, obj, args[0]); |
| 648 #endif |
630 return obj->map()->is_extensible() ? Heap::true_value() | 649 return obj->map()->is_extensible() ? Heap::true_value() |
631 : Heap::false_value(); | 650 : Heap::false_value(); |
632 } | 651 } |
633 | 652 |
634 | 653 |
635 static Object* Runtime_RegExpCompile(Arguments args) { | 654 static Object* Runtime_RegExpCompile(Arguments args) { |
636 HandleScope scope; | 655 HandleScope scope; |
637 ASSERT(args.length() == 3); | 656 ASSERT(args.length() == 3); |
638 CONVERT_ARG_CHECKED(JSRegExp, re, 0); | 657 CONVERT_ARG_CHECKED(JSRegExp, re, 0); |
639 CONVERT_ARG_CHECKED(String, pattern, 1); | 658 CONVERT_ARG_CHECKED(String, pattern, 1); |
(...skipping 613 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1253 &has_pending_exception); | 1272 &has_pending_exception); |
1254 if (has_pending_exception) { | 1273 if (has_pending_exception) { |
1255 ASSERT(Top::has_pending_exception()); | 1274 ASSERT(Top::has_pending_exception()); |
1256 return Failure::Exception(); | 1275 return Failure::Exception(); |
1257 } | 1276 } |
1258 literals->set(index, *regexp); | 1277 literals->set(index, *regexp); |
1259 return *regexp; | 1278 return *regexp; |
1260 } | 1279 } |
1261 | 1280 |
1262 | 1281 |
| 1282 #ifdef DIRECT_CALL_SUPPORTED |
| 1283 static Object* Runtime_FunctionGetName(Object* arg) { |
| 1284 AssertNoAllocation na; |
| 1285 |
| 1286 ASSERT(arg->IsJSFunction()); |
| 1287 JSFunction* f = JSFunction::cast(arg); |
| 1288 #else |
1263 static Object* Runtime_FunctionGetName(Arguments args) { | 1289 static Object* Runtime_FunctionGetName(Arguments args) { |
1264 NoHandleAllocation ha; | 1290 NoHandleAllocation ha; |
1265 ASSERT(args.length() == 1); | 1291 ASSERT(args.length() == 1); |
1266 | 1292 |
1267 CONVERT_CHECKED(JSFunction, f, args[0]); | 1293 CONVERT_CHECKED(JSFunction, f, args[0]); |
| 1294 #endif |
1268 return f->shared()->name(); | 1295 return f->shared()->name(); |
1269 } | 1296 } |
1270 | 1297 |
1271 | 1298 |
| 1299 #ifdef DIRECT_CALL_SUPPORTED |
| 1300 static Object* Runtime_FunctionSetName(Object* arg0, Object* arg1) { |
| 1301 AssertNoAllocation na; |
| 1302 |
| 1303 ASSERT(arg0->IsJSFunction()); |
| 1304 JSFunction* f = JSFunction::cast(arg0); |
| 1305 ASSERT(arg1->IsString()); |
| 1306 String* name = String::cast(arg1); |
| 1307 #else |
1272 static Object* Runtime_FunctionSetName(Arguments args) { | 1308 static Object* Runtime_FunctionSetName(Arguments args) { |
1273 NoHandleAllocation ha; | 1309 NoHandleAllocation ha; |
1274 ASSERT(args.length() == 2); | 1310 ASSERT(args.length() == 2); |
1275 | 1311 |
1276 CONVERT_CHECKED(JSFunction, f, args[0]); | 1312 CONVERT_CHECKED(JSFunction, f, args[0]); |
1277 CONVERT_CHECKED(String, name, args[1]); | 1313 CONVERT_CHECKED(String, name, args[1]); |
| 1314 #endif |
1278 f->shared()->set_name(name); | 1315 f->shared()->set_name(name); |
1279 return Heap::undefined_value(); | 1316 return Heap::undefined_value(); |
1280 } | 1317 } |
1281 | 1318 |
1282 | 1319 |
1283 static Object* Runtime_FunctionGetScript(Arguments args) { | 1320 static Object* Runtime_FunctionGetScript(Arguments args) { |
1284 HandleScope scope; | 1321 HandleScope scope; |
1285 ASSERT(args.length() == 1); | 1322 ASSERT(args.length() == 1); |
1286 | 1323 |
1287 CONVERT_CHECKED(JSFunction, fun, args[0]); | 1324 CONVERT_CHECKED(JSFunction, fun, args[0]); |
(...skipping 1196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2484 break; | 2521 break; |
2485 } | 2522 } |
2486 } | 2523 } |
2487 if (found) return Smi::FromInt(i); | 2524 if (found) return Smi::FromInt(i); |
2488 } | 2525 } |
2489 | 2526 |
2490 return Smi::FromInt(-1); | 2527 return Smi::FromInt(-1); |
2491 } | 2528 } |
2492 | 2529 |
2493 | 2530 |
| 2531 #ifdef DIRECT_CALL_SUPPORTED |
| 2532 static Object* Runtime_StringLocaleCompare(Object* arg0, Object* arg1) { |
| 2533 AssertNoAllocation na; |
| 2534 String* str1 = String::cast(arg0); |
| 2535 String* str2 = String::cast(arg1); |
| 2536 #else |
2494 static Object* Runtime_StringLocaleCompare(Arguments args) { | 2537 static Object* Runtime_StringLocaleCompare(Arguments args) { |
2495 NoHandleAllocation ha; | 2538 NoHandleAllocation ha; |
2496 ASSERT(args.length() == 2); | 2539 ASSERT(args.length() == 2); |
2497 | 2540 |
2498 CONVERT_CHECKED(String, str1, args[0]); | 2541 CONVERT_CHECKED(String, str1, args[0]); |
2499 CONVERT_CHECKED(String, str2, args[1]); | 2542 CONVERT_CHECKED(String, str2, args[1]); |
| 2543 #endif |
2500 | 2544 |
2501 if (str1 == str2) return Smi::FromInt(0); // Equal. | 2545 if (str1 == str2) return Smi::FromInt(0); // Equal. |
2502 int str1_length = str1->length(); | 2546 int str1_length = str1->length(); |
2503 int str2_length = str2->length(); | 2547 int str2_length = str2->length(); |
2504 | 2548 |
2505 // Decide trivial cases without flattening. | 2549 // Decide trivial cases without flattening. |
2506 if (str1_length == 0) { | 2550 if (str1_length == 0) { |
2507 if (str2_length == 0) return Smi::FromInt(0); // Equal. | 2551 if (str2_length == 0) return Smi::FromInt(0); // Equal. |
2508 return Smi::FromInt(-str2_length); | 2552 return Smi::FromInt(-str2_length); |
2509 } else { | 2553 } else { |
(...skipping 1021 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3531 ASSERT(args.length() == 1); | 3575 ASSERT(args.length() == 1); |
3532 Handle<Object> object = args.at<Object>(0); | 3576 Handle<Object> object = args.at<Object>(0); |
3533 if (object->IsJSObject()) { | 3577 if (object->IsJSObject()) { |
3534 Handle<JSObject> js_object = Handle<JSObject>::cast(object); | 3578 Handle<JSObject> js_object = Handle<JSObject>::cast(object); |
3535 js_object->NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); | 3579 js_object->NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); |
3536 } | 3580 } |
3537 return *object; | 3581 return *object; |
3538 } | 3582 } |
3539 | 3583 |
3540 | 3584 |
| 3585 #ifdef DIRECT_CALL_SUPPORTED |
| 3586 static Object* Runtime_ToBool(Object* arg) { |
| 3587 AssertNoAllocation na; |
| 3588 |
| 3589 return arg->ToBoolean(); |
| 3590 } |
| 3591 #else |
3541 static Object* Runtime_ToBool(Arguments args) { | 3592 static Object* Runtime_ToBool(Arguments args) { |
3542 NoHandleAllocation ha; | 3593 NoHandleAllocation ha; |
3543 ASSERT(args.length() == 1); | 3594 ASSERT(args.length() == 1); |
3544 | 3595 |
3545 return args[0]->ToBoolean(); | 3596 return args[0]->ToBoolean(); |
3546 } | 3597 } |
| 3598 #endif |
3547 | 3599 |
3548 | 3600 |
3549 // Returns the type string of a value; see ECMA-262, 11.4.3 (p 47). | 3601 // Returns the type string of a value; see ECMA-262, 11.4.3 (p 47). |
3550 // Possible optimizations: put the type string into the oddballs. | 3602 // Possible optimizations: put the type string into the oddballs. |
| 3603 #ifdef DIRECT_CALL_SUPPORTED |
| 3604 static Object* Runtime_Typeof(Object* obj) { |
| 3605 AssertNoAllocation na; |
| 3606 #else |
3551 static Object* Runtime_Typeof(Arguments args) { | 3607 static Object* Runtime_Typeof(Arguments args) { |
3552 NoHandleAllocation ha; | 3608 NoHandleAllocation ha; |
3553 | |
3554 Object* obj = args[0]; | 3609 Object* obj = args[0]; |
| 3610 #endif |
3555 if (obj->IsNumber()) return Heap::number_symbol(); | 3611 if (obj->IsNumber()) return Heap::number_symbol(); |
3556 HeapObject* heap_obj = HeapObject::cast(obj); | 3612 HeapObject* heap_obj = HeapObject::cast(obj); |
3557 | 3613 |
3558 // typeof an undetectable object is 'undefined' | 3614 // typeof an undetectable object is 'undefined' |
3559 if (heap_obj->map()->is_undetectable()) return Heap::undefined_symbol(); | 3615 if (heap_obj->map()->is_undetectable()) return Heap::undefined_symbol(); |
3560 | 3616 |
3561 InstanceType instance_type = heap_obj->map()->instance_type(); | 3617 InstanceType instance_type = heap_obj->map()->instance_type(); |
3562 if (instance_type < FIRST_NONSTRING_TYPE) { | 3618 if (instance_type < FIRST_NONSTRING_TYPE) { |
3563 return Heap::string_symbol(); | 3619 return Heap::string_symbol(); |
3564 } | 3620 } |
(...skipping 529 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4094 | 4150 |
4095 Object* obj = args[0]; | 4151 Object* obj = args[0]; |
4096 if (obj->IsSmi()) return obj; | 4152 if (obj->IsSmi()) return obj; |
4097 CONVERT_DOUBLE_CHECKED(number, obj); | 4153 CONVERT_DOUBLE_CHECKED(number, obj); |
4098 return Heap::NumberFromInt32(DoubleToInt32(number)); | 4154 return Heap::NumberFromInt32(DoubleToInt32(number)); |
4099 } | 4155 } |
4100 | 4156 |
4101 | 4157 |
4102 // Converts a Number to a Smi, if possible. Returns NaN if the number is not | 4158 // Converts a Number to a Smi, if possible. Returns NaN if the number is not |
4103 // a small integer. | 4159 // a small integer. |
| 4160 #ifdef DIRECT_CALL_SUPPORTED |
| 4161 static Object* Runtime_NumberToSmi(Object* obj) { |
| 4162 AssertNoAllocation na; |
| 4163 #else |
4104 static Object* Runtime_NumberToSmi(Arguments args) { | 4164 static Object* Runtime_NumberToSmi(Arguments args) { |
4105 NoHandleAllocation ha; | 4165 NoHandleAllocation ha; |
4106 ASSERT(args.length() == 1); | 4166 ASSERT(args.length() == 1); |
4107 | 4167 |
4108 Object* obj = args[0]; | 4168 Object* obj = args[0]; |
| 4169 #endif |
4109 if (obj->IsSmi()) { | 4170 if (obj->IsSmi()) { |
4110 return obj; | 4171 return obj; |
4111 } | 4172 } |
4112 if (obj->IsHeapNumber()) { | 4173 if (obj->IsHeapNumber()) { |
4113 double value = HeapNumber::cast(obj)->value(); | 4174 double value = HeapNumber::cast(obj)->value(); |
4114 int int_value = FastD2I(value); | 4175 int int_value = FastD2I(value); |
4115 if (value == FastI2D(int_value) && Smi::IsValid(int_value)) { | 4176 if (value == FastI2D(int_value) && Smi::IsValid(int_value)) { |
4116 return Smi::FromInt(int_value); | 4177 return Smi::FromInt(int_value); |
4117 } | 4178 } |
4118 } | 4179 } |
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4394 static Object* Runtime_NumberSar(Arguments args) { | 4455 static Object* Runtime_NumberSar(Arguments args) { |
4395 NoHandleAllocation ha; | 4456 NoHandleAllocation ha; |
4396 ASSERT(args.length() == 2); | 4457 ASSERT(args.length() == 2); |
4397 | 4458 |
4398 CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]); | 4459 CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]); |
4399 CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]); | 4460 CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]); |
4400 return Heap::NumberFromInt32(ArithmeticShiftRight(x, y & 0x1f)); | 4461 return Heap::NumberFromInt32(ArithmeticShiftRight(x, y & 0x1f)); |
4401 } | 4462 } |
4402 | 4463 |
4403 | 4464 |
| 4465 #ifdef DIRECT_CALL_SUPPORTED |
| 4466 static Object* Runtime_NumberEquals(Object* arg0, Object* arg1) { |
| 4467 AssertNoAllocation na; |
| 4468 |
| 4469 ASSERT(arg0->IsNumber()); |
| 4470 double x = arg0->Number(); |
| 4471 ASSERT(arg1->IsNumber()); |
| 4472 double y = arg1->Number(); |
| 4473 #else |
4404 static Object* Runtime_NumberEquals(Arguments args) { | 4474 static Object* Runtime_NumberEquals(Arguments args) { |
4405 NoHandleAllocation ha; | 4475 NoHandleAllocation ha; |
4406 ASSERT(args.length() == 2); | 4476 ASSERT(args.length() == 2); |
4407 | 4477 |
4408 CONVERT_DOUBLE_CHECKED(x, args[0]); | 4478 CONVERT_DOUBLE_CHECKED(x, args[0]); |
4409 CONVERT_DOUBLE_CHECKED(y, args[1]); | 4479 CONVERT_DOUBLE_CHECKED(y, args[1]); |
| 4480 #endif |
4410 if (isnan(x)) return Smi::FromInt(NOT_EQUAL); | 4481 if (isnan(x)) return Smi::FromInt(NOT_EQUAL); |
4411 if (isnan(y)) return Smi::FromInt(NOT_EQUAL); | 4482 if (isnan(y)) return Smi::FromInt(NOT_EQUAL); |
4412 if (x == y) return Smi::FromInt(EQUAL); | 4483 if (x == y) return Smi::FromInt(EQUAL); |
4413 Object* result; | 4484 Object* result; |
4414 if ((fpclassify(x) == FP_ZERO) && (fpclassify(y) == FP_ZERO)) { | 4485 if ((fpclassify(x) == FP_ZERO) && (fpclassify(y) == FP_ZERO)) { |
4415 result = Smi::FromInt(EQUAL); | 4486 result = Smi::FromInt(EQUAL); |
4416 } else { | 4487 } else { |
4417 result = Smi::FromInt(NOT_EQUAL); | 4488 result = Smi::FromInt(NOT_EQUAL); |
4418 } | 4489 } |
4419 return result; | 4490 return result; |
4420 } | 4491 } |
4421 | 4492 |
4422 | 4493 |
| 4494 #ifdef DIRECT_CALL_SUPPORTED |
| 4495 static Object* Runtime_StringEquals(Object* arg0, Object* arg1) { |
| 4496 AssertNoAllocation na; |
| 4497 |
| 4498 ASSERT(arg0->IsString()); |
| 4499 String* x = String::cast(arg0); |
| 4500 ASSERT(arg1->IsString()); |
| 4501 String* y = String::cast(arg1); |
| 4502 #else |
4423 static Object* Runtime_StringEquals(Arguments args) { | 4503 static Object* Runtime_StringEquals(Arguments args) { |
4424 NoHandleAllocation ha; | 4504 NoHandleAllocation ha; |
4425 ASSERT(args.length() == 2); | 4505 ASSERT(args.length() == 2); |
4426 | 4506 |
4427 CONVERT_CHECKED(String, x, args[0]); | 4507 CONVERT_CHECKED(String, x, args[0]); |
4428 CONVERT_CHECKED(String, y, args[1]); | 4508 CONVERT_CHECKED(String, y, args[1]); |
| 4509 #endif |
4429 | 4510 |
4430 bool not_equal = !x->Equals(y); | 4511 bool not_equal = !x->Equals(y); |
4431 // This is slightly convoluted because the value that signifies | 4512 // This is slightly convoluted because the value that signifies |
4432 // equality is 0 and inequality is 1 so we have to negate the result | 4513 // equality is 0 and inequality is 1 so we have to negate the result |
4433 // from String::Equals. | 4514 // from String::Equals. |
4434 ASSERT(not_equal == 0 || not_equal == 1); | 4515 ASSERT(not_equal == 0 || not_equal == 1); |
4435 STATIC_CHECK(EQUAL == 0); | 4516 STATIC_CHECK(EQUAL == 0); |
4436 STATIC_CHECK(NOT_EQUAL == 1); | 4517 STATIC_CHECK(NOT_EQUAL == 1); |
4437 return Smi::FromInt(not_equal); | 4518 return Smi::FromInt(not_equal); |
4438 } | 4519 } |
4439 | 4520 |
4440 | 4521 |
| 4522 #ifdef DIRECT_CALL_SUPPORTED |
| 4523 static Object* Runtime_NumberCompare(Object* arg0, Object* arg1, Object* arg2) { |
| 4524 NoHandleAllocation ha; |
| 4525 |
| 4526 ASSERT(arg0->IsNumber()); |
| 4527 double x = arg0->Number(); |
| 4528 ASSERT(arg1->IsNumber()); |
| 4529 double y = arg1->Number(); |
| 4530 if (isnan(x) || isnan(y)) return arg2; |
| 4531 #else |
4441 static Object* Runtime_NumberCompare(Arguments args) { | 4532 static Object* Runtime_NumberCompare(Arguments args) { |
4442 NoHandleAllocation ha; | 4533 NoHandleAllocation ha; |
4443 ASSERT(args.length() == 3); | 4534 ASSERT(args.length() == 3); |
4444 | 4535 |
4445 CONVERT_DOUBLE_CHECKED(x, args[0]); | 4536 CONVERT_DOUBLE_CHECKED(x, args[0]); |
4446 CONVERT_DOUBLE_CHECKED(y, args[1]); | 4537 CONVERT_DOUBLE_CHECKED(y, args[1]); |
4447 if (isnan(x) || isnan(y)) return args[2]; | 4538 if (isnan(x) || isnan(y)) return args[2]; |
| 4539 #endif |
4448 if (x == y) return Smi::FromInt(EQUAL); | 4540 if (x == y) return Smi::FromInt(EQUAL); |
4449 if (isless(x, y)) return Smi::FromInt(LESS); | 4541 if (isless(x, y)) return Smi::FromInt(LESS); |
4450 return Smi::FromInt(GREATER); | 4542 return Smi::FromInt(GREATER); |
4451 } | 4543 } |
4452 | 4544 |
4453 | 4545 |
4454 // Compare two Smis as if they were converted to strings and then | 4546 // Compare two Smis as if they were converted to strings and then |
4455 // compared lexicographically. | 4547 // compared lexicographically. |
| 4548 #ifdef DIRECT_CALL_SUPPORTED |
| 4549 static Object* Runtime_SmiLexicographicCompare(Object* arg0, Object* arg1) { |
| 4550 AssertNoAllocation na; |
| 4551 |
| 4552 // Extract the integer values from the Smis. |
| 4553 ASSERT(arg0->IsSmi()); |
| 4554 Smi* x = Smi::cast(arg0); |
| 4555 ASSERT(arg1->IsSmi()); |
| 4556 Smi* y = Smi::cast(arg1); |
| 4557 #else |
4456 static Object* Runtime_SmiLexicographicCompare(Arguments args) { | 4558 static Object* Runtime_SmiLexicographicCompare(Arguments args) { |
4457 NoHandleAllocation ha; | 4559 NoHandleAllocation ha; |
4458 ASSERT(args.length() == 2); | 4560 ASSERT(args.length() == 2); |
4459 | 4561 |
| 4562 // Extract the integer values from the Smis. |
| 4563 CONVERT_CHECKED(Smi, x, args[0]); |
| 4564 CONVERT_CHECKED(Smi, y, args[1]); |
| 4565 #endif |
| 4566 |
4460 // Arrays for the individual characters of the two Smis. Smis are | 4567 // Arrays for the individual characters of the two Smis. Smis are |
4461 // 31 bit integers and 10 decimal digits are therefore enough. | 4568 // 31 bit integers and 10 decimal digits are therefore enough. |
4462 static int x_elms[10]; | 4569 static int x_elms[10]; |
4463 static int y_elms[10]; | 4570 static int y_elms[10]; |
4464 | 4571 |
4465 // Extract the integer values from the Smis. | |
4466 CONVERT_CHECKED(Smi, x, args[0]); | |
4467 CONVERT_CHECKED(Smi, y, args[1]); | |
4468 int x_value = x->value(); | 4572 int x_value = x->value(); |
4469 int y_value = y->value(); | 4573 int y_value = y->value(); |
4470 | 4574 |
4471 // If the integers are equal so are the string representations. | 4575 // If the integers are equal so are the string representations. |
4472 if (x_value == y_value) return Smi::FromInt(EQUAL); | 4576 if (x_value == y_value) return Smi::FromInt(EQUAL); |
4473 | 4577 |
4474 // If one of the integers are zero the normal integer order is the | 4578 // If one of the integers are zero the normal integer order is the |
4475 // same as the lexicographic order of the string representations. | 4579 // same as the lexicographic order of the string representations. |
4476 if (x_value == 0 || y_value == 0) return Smi::FromInt(x_value - y_value); | 4580 if (x_value == 0 || y_value == 0) return Smi::FromInt(x_value - y_value); |
4477 | 4581 |
(...skipping 26 matching lines...) Expand all Loading... |
4504 if (diff != 0) return Smi::FromInt(diff); | 4608 if (diff != 0) return Smi::FromInt(diff); |
4505 } | 4609 } |
4506 | 4610 |
4507 // If one array is a suffix of the other array, the longest array is | 4611 // If one array is a suffix of the other array, the longest array is |
4508 // the representation of the largest of the Smis in the | 4612 // the representation of the largest of the Smis in the |
4509 // lexicographic ordering. | 4613 // lexicographic ordering. |
4510 return Smi::FromInt(x_index - y_index); | 4614 return Smi::FromInt(x_index - y_index); |
4511 } | 4615 } |
4512 | 4616 |
4513 | 4617 |
| 4618 #ifdef DIRECT_CALL_SUPPORTED |
| 4619 static Object* Runtime_StringCompare(Object* arg0, Object* arg1) { |
| 4620 AssertNoAllocation na; |
| 4621 |
| 4622 ASSERT(arg0->IsString()); |
| 4623 String* x = String::cast(arg0); |
| 4624 ASSERT(arg1->IsString()); |
| 4625 String* y = String::cast(arg1); |
| 4626 #else |
4514 static Object* Runtime_StringCompare(Arguments args) { | 4627 static Object* Runtime_StringCompare(Arguments args) { |
4515 NoHandleAllocation ha; | 4628 NoHandleAllocation ha; |
4516 ASSERT(args.length() == 2); | 4629 ASSERT(args.length() == 2); |
4517 | 4630 |
4518 CONVERT_CHECKED(String, x, args[0]); | 4631 CONVERT_CHECKED(String, x, args[0]); |
4519 CONVERT_CHECKED(String, y, args[1]); | 4632 CONVERT_CHECKED(String, y, args[1]); |
| 4633 #endif |
4520 | 4634 |
4521 Counters::string_compare_runtime.Increment(); | 4635 Counters::string_compare_runtime.Increment(); |
4522 | 4636 |
4523 // A few fast case tests before we flatten. | 4637 // A few fast case tests before we flatten. |
4524 if (x == y) return Smi::FromInt(EQUAL); | 4638 if (x == y) return Smi::FromInt(EQUAL); |
4525 if (y->length() == 0) { | 4639 if (y->length() == 0) { |
4526 if (x->length() == 0) return Smi::FromInt(EQUAL); | 4640 if (x->length() == 0) return Smi::FromInt(EQUAL); |
4527 return Smi::FromInt(GREATER); | 4641 return Smi::FromInt(GREATER); |
4528 } else if (x->length() == 0) { | 4642 } else if (x->length() == 0) { |
4529 return Smi::FromInt(LESS); | 4643 return Smi::FromInt(LESS); |
(...skipping 920 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5450 | 5564 |
5451 static Object* Runtime_DateDaylightSavingsOffset(Arguments args) { | 5565 static Object* Runtime_DateDaylightSavingsOffset(Arguments args) { |
5452 NoHandleAllocation ha; | 5566 NoHandleAllocation ha; |
5453 ASSERT(args.length() == 1); | 5567 ASSERT(args.length() == 1); |
5454 | 5568 |
5455 CONVERT_DOUBLE_CHECKED(x, args[0]); | 5569 CONVERT_DOUBLE_CHECKED(x, args[0]); |
5456 return Heap::NumberFromDouble(OS::DaylightSavingsOffset(x)); | 5570 return Heap::NumberFromDouble(OS::DaylightSavingsOffset(x)); |
5457 } | 5571 } |
5458 | 5572 |
5459 | 5573 |
| 5574 #ifdef DIRECT_CALL_SUPPORTED |
| 5575 static Object* Runtime_NumberIsFinite(Object* arg0) { |
| 5576 AssertNoAllocation na; |
| 5577 ASSERT(arg0->IsNumber()); |
| 5578 double value = arg0->Number(); |
| 5579 #else |
5460 static Object* Runtime_NumberIsFinite(Arguments args) { | 5580 static Object* Runtime_NumberIsFinite(Arguments args) { |
5461 NoHandleAllocation ha; | 5581 NoHandleAllocation ha; |
5462 ASSERT(args.length() == 1); | 5582 ASSERT(args.length() == 1); |
5463 | 5583 |
5464 CONVERT_DOUBLE_CHECKED(value, args[0]); | 5584 CONVERT_DOUBLE_CHECKED(value, args[0]); |
| 5585 #endif |
5465 Object* result; | 5586 Object* result; |
5466 if (isnan(value) || (fpclassify(value) == FP_INFINITE)) { | 5587 if (isnan(value) || (fpclassify(value) == FP_INFINITE)) { |
5467 result = Heap::false_value(); | 5588 result = Heap::false_value(); |
5468 } else { | 5589 } else { |
5469 result = Heap::true_value(); | 5590 result = Heap::true_value(); |
5470 } | 5591 } |
5471 return result; | 5592 return result; |
5472 } | 5593 } |
5473 | 5594 |
5474 | 5595 |
(...skipping 2627 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8102 | 8223 |
8103 #ifdef DEBUG | 8224 #ifdef DEBUG |
8104 // ListNatives is ONLY used by the fuzz-natives.js in debug mode | 8225 // ListNatives is ONLY used by the fuzz-natives.js in debug mode |
8105 // Exclude the code in release mode. | 8226 // Exclude the code in release mode. |
8106 static Object* Runtime_ListNatives(Arguments args) { | 8227 static Object* Runtime_ListNatives(Arguments args) { |
8107 ASSERT(args.length() == 0); | 8228 ASSERT(args.length() == 0); |
8108 HandleScope scope; | 8229 HandleScope scope; |
8109 Handle<JSArray> result = Factory::NewJSArray(0); | 8230 Handle<JSArray> result = Factory::NewJSArray(0); |
8110 int index = 0; | 8231 int index = 0; |
8111 #define ADD_ENTRY(Name, argc, ressize) \ | 8232 #define ADD_ENTRY(Name, argc, ressize) \ |
8112 { \ | 8233 if (Runtime::FunctionForId(Runtime::k##Name)->calling_convention != \ |
| 8234 Runtime::DIRECT_CALL_NOT_FAILS) { \ |
8113 HandleScope inner; \ | 8235 HandleScope inner; \ |
8114 Handle<String> name = \ | 8236 Handle<String> name = \ |
8115 Factory::NewStringFromAscii( \ | 8237 Factory::NewStringFromAscii( \ |
8116 Vector<const char>(#Name, StrLength(#Name))); \ | 8238 Vector<const char>(#Name, StrLength(#Name))); \ |
8117 Handle<JSArray> pair = Factory::NewJSArray(0); \ | 8239 Handle<JSArray> pair = Factory::NewJSArray(0); \ |
8118 SetElement(pair, 0, name); \ | 8240 SetElement(pair, 0, name); \ |
8119 SetElement(pair, 1, Handle<Smi>(Smi::FromInt(argc))); \ | 8241 SetElement(pair, 1, Handle<Smi>(Smi::FromInt(argc))); \ |
8120 SetElement(result, index++, pair); \ | 8242 SetElement(result, index++, pair); \ |
8121 } | 8243 } |
8122 RUNTIME_FUNCTION_LIST(ADD_ENTRY) | 8244 RUNTIME_FUNCTION_LIST(ADD_ENTRY) |
(...skipping 11 matching lines...) Expand all Loading... |
8134 Logger::LogRuntime(chars, elms); | 8256 Logger::LogRuntime(chars, elms); |
8135 return Heap::undefined_value(); | 8257 return Heap::undefined_value(); |
8136 } | 8258 } |
8137 | 8259 |
8138 | 8260 |
8139 static Object* Runtime_IS_VAR(Arguments args) { | 8261 static Object* Runtime_IS_VAR(Arguments args) { |
8140 UNREACHABLE(); // implemented as macro in the parser | 8262 UNREACHABLE(); // implemented as macro in the parser |
8141 return NULL; | 8263 return NULL; |
8142 } | 8264 } |
8143 | 8265 |
| 8266 // ---------------------------------------------------------------------------- |
| 8267 // Utilities for building the runtime function list |
| 8268 namespace { |
| 8269 |
| 8270 template <size_t kId> |
| 8271 class SignatureTag { |
| 8272 char a[kId]; // there is a biection between id and sizeof(SignatureTag<kId>) |
| 8273 }; |
| 8274 |
| 8275 |
| 8276 template <size_t signature_tag_size> struct FunctionTraits; |
| 8277 |
| 8278 |
| 8279 #define SIGNATURE_TRAITS(id, signature) \ |
| 8280 SignatureTag<id> GetTag(signature); \ |
| 8281 template <> struct FunctionTraits<sizeof(SignatureTag<id>)> |
| 8282 |
| 8283 SIGNATURE_TRAITS(1, Object* (*)(Arguments)) { |
| 8284 static const Runtime::CallingConvention conv = Runtime::EXIT_FRAME_CALL; |
| 8285 }; |
| 8286 |
| 8287 |
| 8288 SIGNATURE_TRAITS(2, ObjectPair (*)(Arguments)) { |
| 8289 static const Runtime::CallingConvention conv = Runtime::EXIT_FRAME_CALL; |
| 8290 }; |
| 8291 |
| 8292 |
| 8293 SIGNATURE_TRAITS(3, Object* (*)(Object* arg)) { |
| 8294 static const Runtime::CallingConvention conv = Runtime::DIRECT_CALL_NOT_FAILS; |
| 8295 }; |
| 8296 |
| 8297 |
| 8298 SIGNATURE_TRAITS(4, Object* (*)(Object* agr0, Object* arg1)) { |
| 8299 static const Runtime::CallingConvention conv = Runtime::DIRECT_CALL_NOT_FAILS; |
| 8300 }; |
| 8301 |
| 8302 SIGNATURE_TRAITS(5, Object* (*)(Object* arg0, Object* arg1, Object* arg2)) { |
| 8303 static const Runtime::CallingConvention conv = Runtime::DIRECT_CALL_NOT_FAILS; |
| 8304 }; |
| 8305 } |
8144 | 8306 |
8145 // ---------------------------------------------------------------------------- | 8307 // ---------------------------------------------------------------------------- |
8146 // Implementation of Runtime | 8308 // Implementation of Runtime |
8147 | 8309 |
8148 #define F(name, nargs, ressize) \ | 8310 #define F(name, nargs, ressize) \ |
8149 { #name, FUNCTION_ADDR(Runtime_##name), nargs, \ | 8311 { #name, FUNCTION_ADDR(Runtime_##name), nargs, \ |
8150 static_cast<int>(Runtime::k##name), ressize }, | 8312 static_cast<int>(Runtime::k##name), ressize, \ |
| 8313 FunctionTraits<sizeof(GetTag(Runtime_##name))>::conv}, |
8151 | 8314 |
8152 static Runtime::Function Runtime_functions[] = { | 8315 static Runtime::Function Runtime_functions[] = { |
8153 RUNTIME_FUNCTION_LIST(F) | 8316 RUNTIME_FUNCTION_LIST(F) |
8154 { NULL, NULL, 0, -1, 0 } | 8317 { NULL, NULL, 0, -1, 0, Runtime::EXIT_FRAME_CALL } |
8155 }; | 8318 }; |
8156 | 8319 |
8157 #undef F | 8320 #undef F |
8158 | 8321 |
8159 | 8322 |
8160 Runtime::Function* Runtime::FunctionForId(FunctionId fid) { | 8323 Runtime::Function* Runtime::FunctionForId(FunctionId fid) { |
8161 ASSERT(0 <= fid && fid < kNofFunctions); | 8324 ASSERT(0 <= fid && fid < kNofFunctions); |
8162 return &Runtime_functions[fid]; | 8325 return &Runtime_functions[fid]; |
8163 } | 8326 } |
8164 | 8327 |
(...skipping 17 matching lines...) Expand all Loading... |
8182 } else { | 8345 } else { |
8183 // Handle last resort GC and make sure to allow future allocations | 8346 // Handle last resort GC and make sure to allow future allocations |
8184 // to grow the heap without causing GCs (if possible). | 8347 // to grow the heap without causing GCs (if possible). |
8185 Counters::gc_last_resort_from_js.Increment(); | 8348 Counters::gc_last_resort_from_js.Increment(); |
8186 Heap::CollectAllGarbage(false); | 8349 Heap::CollectAllGarbage(false); |
8187 } | 8350 } |
8188 } | 8351 } |
8189 | 8352 |
8190 | 8353 |
8191 } } // namespace v8::internal | 8354 } } // namespace v8::internal |
OLD | NEW |