| 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 |