| Index: src/runtime.cc
|
| ===================================================================
|
| --- src/runtime.cc (revision 3911)
|
| +++ src/runtime.cc (working copy)
|
| @@ -49,6 +49,9 @@
|
| namespace v8 {
|
| namespace internal {
|
|
|
| +#if defined(V8_TARGET_ARCH_X64) || defined(V8_TARGET_ARCH_IA32)
|
| +#define DIRECT_CALL_SUPPORTED
|
| +#endif
|
|
|
| #define RUNTIME_ASSERT(value) \
|
| if (!(value)) return Top::ThrowIllegalOperation();
|
| @@ -487,22 +490,31 @@
|
| return object;
|
| }
|
|
|
| -
|
| +#ifdef DIRECT_CALL_SUPPORTED
|
| +static Object* Runtime_ClassOf(Object* obj) {
|
| + AssertNoAllocation na;
|
| +#else
|
| static Object* Runtime_ClassOf(Arguments args) {
|
| NoHandleAllocation ha;
|
| ASSERT(args.length() == 1);
|
| Object* obj = args[0];
|
| +#endif
|
| if (!obj->IsJSObject()) return Heap::null_value();
|
| return JSObject::cast(obj)->class_name();
|
| }
|
|
|
|
|
| +#ifdef DIRECT_CALL_SUPPORTED
|
| +static Object* Runtime_IsInPrototypeChain(Object* O, Object* V) {
|
| + AssertNoAllocation na;
|
| +#else
|
| static Object* Runtime_IsInPrototypeChain(Arguments args) {
|
| NoHandleAllocation ha;
|
| ASSERT(args.length() == 2);
|
| - // See ECMA-262, section 15.3.5.3, page 88 (steps 5 - 8).
|
| Object* O = args[0];
|
| Object* V = args[1];
|
| +#endif
|
| + // See ECMA-262, section 15.3.5.3, page 88 (steps 5 - 8).
|
| while (true) {
|
| Object* prototype = V->GetPrototype();
|
| if (prototype->IsNull()) return Heap::false_value();
|
| @@ -624,9 +636,16 @@
|
| }
|
|
|
|
|
| +#ifdef DIRECT_CALL_SUPPORTED
|
| +static Object* Runtime_IsExtensible(Object* arg) {
|
| + AssertNoAllocation na;
|
| + ASSERT(arg->IsJSObject());
|
| + JSObject* obj = JSObject::cast(arg);
|
| +#else
|
| static Object* Runtime_IsExtensible(Arguments args) {
|
| ASSERT(args.length() == 1);
|
| CONVERT_CHECKED(JSObject, obj, args[0]);
|
| +#endif
|
| return obj->map()->is_extensible() ? Heap::true_value()
|
| : Heap::false_value();
|
| }
|
| @@ -1260,21 +1279,39 @@
|
| }
|
|
|
|
|
| +#ifdef DIRECT_CALL_SUPPORTED
|
| +static Object* Runtime_FunctionGetName(Object* arg) {
|
| + AssertNoAllocation na;
|
| +
|
| + ASSERT(arg->IsJSFunction());
|
| + JSFunction* f = JSFunction::cast(arg);
|
| +#else
|
| static Object* Runtime_FunctionGetName(Arguments args) {
|
| NoHandleAllocation ha;
|
| ASSERT(args.length() == 1);
|
|
|
| CONVERT_CHECKED(JSFunction, f, args[0]);
|
| +#endif
|
| return f->shared()->name();
|
| }
|
|
|
|
|
| +#ifdef DIRECT_CALL_SUPPORTED
|
| +static Object* Runtime_FunctionSetName(Object* arg0, Object* arg1) {
|
| + AssertNoAllocation na;
|
| +
|
| + ASSERT(arg0->IsJSFunction());
|
| + JSFunction* f = JSFunction::cast(arg0);
|
| + ASSERT(arg1->IsString());
|
| + String* name = String::cast(arg1);
|
| +#else
|
| static Object* Runtime_FunctionSetName(Arguments args) {
|
| NoHandleAllocation ha;
|
| ASSERT(args.length() == 2);
|
|
|
| CONVERT_CHECKED(JSFunction, f, args[0]);
|
| CONVERT_CHECKED(String, name, args[1]);
|
| +#endif
|
| f->shared()->set_name(name);
|
| return Heap::undefined_value();
|
| }
|
| @@ -2491,12 +2528,19 @@
|
| }
|
|
|
|
|
| +#ifdef DIRECT_CALL_SUPPORTED
|
| +static Object* Runtime_StringLocaleCompare(Object* arg0, Object* arg1) {
|
| + AssertNoAllocation na;
|
| + String* str1 = String::cast(arg0);
|
| + String* str2 = String::cast(arg1);
|
| +#else
|
| static Object* Runtime_StringLocaleCompare(Arguments args) {
|
| NoHandleAllocation ha;
|
| ASSERT(args.length() == 2);
|
|
|
| CONVERT_CHECKED(String, str1, args[0]);
|
| CONVERT_CHECKED(String, str2, args[1]);
|
| +#endif
|
|
|
| if (str1 == str2) return Smi::FromInt(0); // Equal.
|
| int str1_length = str1->length();
|
| @@ -3538,20 +3582,32 @@
|
| }
|
|
|
|
|
| +#ifdef DIRECT_CALL_SUPPORTED
|
| +static Object* Runtime_ToBool(Object* arg) {
|
| + AssertNoAllocation na;
|
| +
|
| + return arg->ToBoolean();
|
| +}
|
| +#else
|
| static Object* Runtime_ToBool(Arguments args) {
|
| NoHandleAllocation ha;
|
| ASSERT(args.length() == 1);
|
|
|
| return args[0]->ToBoolean();
|
| }
|
| +#endif
|
|
|
|
|
| // Returns the type string of a value; see ECMA-262, 11.4.3 (p 47).
|
| // Possible optimizations: put the type string into the oddballs.
|
| +#ifdef DIRECT_CALL_SUPPORTED
|
| +static Object* Runtime_Typeof(Object* obj) {
|
| + AssertNoAllocation na;
|
| +#else
|
| static Object* Runtime_Typeof(Arguments args) {
|
| NoHandleAllocation ha;
|
| -
|
| Object* obj = args[0];
|
| +#endif
|
| if (obj->IsNumber()) return Heap::number_symbol();
|
| HeapObject* heap_obj = HeapObject::cast(obj);
|
|
|
| @@ -4101,11 +4157,16 @@
|
|
|
| // Converts a Number to a Smi, if possible. Returns NaN if the number is not
|
| // a small integer.
|
| +#ifdef DIRECT_CALL_SUPPORTED
|
| +static Object* Runtime_NumberToSmi(Object* obj) {
|
| + AssertNoAllocation na;
|
| +#else
|
| static Object* Runtime_NumberToSmi(Arguments args) {
|
| NoHandleAllocation ha;
|
| ASSERT(args.length() == 1);
|
|
|
| Object* obj = args[0];
|
| +#endif
|
| if (obj->IsSmi()) {
|
| return obj;
|
| }
|
| @@ -4401,12 +4462,22 @@
|
| }
|
|
|
|
|
| +#ifdef DIRECT_CALL_SUPPORTED
|
| +static Object* Runtime_NumberEquals(Object* arg0, Object* arg1) {
|
| + AssertNoAllocation na;
|
| +
|
| + ASSERT(arg0->IsNumber());
|
| + double x = arg0->Number();
|
| + ASSERT(arg1->IsNumber());
|
| + double y = arg1->Number();
|
| +#else
|
| static Object* Runtime_NumberEquals(Arguments args) {
|
| NoHandleAllocation ha;
|
| ASSERT(args.length() == 2);
|
|
|
| CONVERT_DOUBLE_CHECKED(x, args[0]);
|
| CONVERT_DOUBLE_CHECKED(y, args[1]);
|
| +#endif
|
| if (isnan(x)) return Smi::FromInt(NOT_EQUAL);
|
| if (isnan(y)) return Smi::FromInt(NOT_EQUAL);
|
| if (x == y) return Smi::FromInt(EQUAL);
|
| @@ -4420,12 +4491,22 @@
|
| }
|
|
|
|
|
| +#ifdef DIRECT_CALL_SUPPORTED
|
| +static Object* Runtime_StringEquals(Object* arg0, Object* arg1) {
|
| + AssertNoAllocation na;
|
| +
|
| + ASSERT(arg0->IsString());
|
| + String* x = String::cast(arg0);
|
| + ASSERT(arg1->IsString());
|
| + String* y = String::cast(arg1);
|
| +#else
|
| static Object* Runtime_StringEquals(Arguments args) {
|
| NoHandleAllocation ha;
|
| ASSERT(args.length() == 2);
|
|
|
| CONVERT_CHECKED(String, x, args[0]);
|
| CONVERT_CHECKED(String, y, args[1]);
|
| +#endif
|
|
|
| bool not_equal = !x->Equals(y);
|
| // This is slightly convoluted because the value that signifies
|
| @@ -4438,6 +4519,16 @@
|
| }
|
|
|
|
|
| +#ifdef DIRECT_CALL_SUPPORTED
|
| +static Object* Runtime_NumberCompare(Object* arg0, Object* arg1, Object* arg2) {
|
| + NoHandleAllocation ha;
|
| +
|
| + ASSERT(arg0->IsNumber());
|
| + double x = arg0->Number();
|
| + ASSERT(arg1->IsNumber());
|
| + double y = arg1->Number();
|
| + if (isnan(x) || isnan(y)) return arg2;
|
| +#else
|
| static Object* Runtime_NumberCompare(Arguments args) {
|
| NoHandleAllocation ha;
|
| ASSERT(args.length() == 3);
|
| @@ -4445,6 +4536,7 @@
|
| CONVERT_DOUBLE_CHECKED(x, args[0]);
|
| CONVERT_DOUBLE_CHECKED(y, args[1]);
|
| if (isnan(x) || isnan(y)) return args[2];
|
| +#endif
|
| if (x == y) return Smi::FromInt(EQUAL);
|
| if (isless(x, y)) return Smi::FromInt(LESS);
|
| return Smi::FromInt(GREATER);
|
| @@ -4453,18 +4545,30 @@
|
|
|
| // Compare two Smis as if they were converted to strings and then
|
| // compared lexicographically.
|
| +#ifdef DIRECT_CALL_SUPPORTED
|
| +static Object* Runtime_SmiLexicographicCompare(Object* arg0, Object* arg1) {
|
| + AssertNoAllocation na;
|
| +
|
| + // Extract the integer values from the Smis.
|
| + ASSERT(arg0->IsSmi());
|
| + Smi* x = Smi::cast(arg0);
|
| + ASSERT(arg1->IsSmi());
|
| + Smi* y = Smi::cast(arg1);
|
| +#else
|
| static Object* Runtime_SmiLexicographicCompare(Arguments args) {
|
| NoHandleAllocation ha;
|
| ASSERT(args.length() == 2);
|
|
|
| + // Extract the integer values from the Smis.
|
| + CONVERT_CHECKED(Smi, x, args[0]);
|
| + CONVERT_CHECKED(Smi, y, args[1]);
|
| +#endif
|
| +
|
| // Arrays for the individual characters of the two Smis. Smis are
|
| // 31 bit integers and 10 decimal digits are therefore enough.
|
| static int x_elms[10];
|
| static int y_elms[10];
|
|
|
| - // Extract the integer values from the Smis.
|
| - CONVERT_CHECKED(Smi, x, args[0]);
|
| - CONVERT_CHECKED(Smi, y, args[1]);
|
| int x_value = x->value();
|
| int y_value = y->value();
|
|
|
| @@ -4511,12 +4615,22 @@
|
| }
|
|
|
|
|
| +#ifdef DIRECT_CALL_SUPPORTED
|
| +static Object* Runtime_StringCompare(Object* arg0, Object* arg1) {
|
| + AssertNoAllocation na;
|
| +
|
| + ASSERT(arg0->IsString());
|
| + String* x = String::cast(arg0);
|
| + ASSERT(arg1->IsString());
|
| + String* y = String::cast(arg1);
|
| +#else
|
| static Object* Runtime_StringCompare(Arguments args) {
|
| NoHandleAllocation ha;
|
| ASSERT(args.length() == 2);
|
|
|
| CONVERT_CHECKED(String, x, args[0]);
|
| CONVERT_CHECKED(String, y, args[1]);
|
| +#endif
|
|
|
| Counters::string_compare_runtime.Increment();
|
|
|
| @@ -5457,11 +5571,18 @@
|
| }
|
|
|
|
|
| +#ifdef DIRECT_CALL_SUPPORTED
|
| +static Object* Runtime_NumberIsFinite(Object* arg0) {
|
| + AssertNoAllocation na;
|
| + ASSERT(arg0->IsNumber());
|
| + double value = arg0->Number();
|
| +#else
|
| static Object* Runtime_NumberIsFinite(Arguments args) {
|
| NoHandleAllocation ha;
|
| ASSERT(args.length() == 1);
|
|
|
| CONVERT_DOUBLE_CHECKED(value, args[0]);
|
| +#endif
|
| Object* result;
|
| if (isnan(value) || (fpclassify(value) == FP_INFINITE)) {
|
| result = Heap::false_value();
|
| @@ -8109,7 +8230,8 @@
|
| Handle<JSArray> result = Factory::NewJSArray(0);
|
| int index = 0;
|
| #define ADD_ENTRY(Name, argc, ressize) \
|
| - { \
|
| + if (Runtime::FunctionForId(Runtime::k##Name)->calling_convention != \
|
| + Runtime::DIRECT_CALL_NOT_FAILS) { \
|
| HandleScope inner; \
|
| Handle<String> name = \
|
| Factory::NewStringFromAscii( \
|
| @@ -8141,17 +8263,58 @@
|
| return NULL;
|
| }
|
|
|
| +// ----------------------------------------------------------------------------
|
| +// Utilities for building the runtime function list
|
| +namespace {
|
|
|
| +template <size_t kId>
|
| +class SignatureTag {
|
| + char a[kId]; // there is a biection between id and sizeof(SignatureTag<kId>)
|
| +};
|
| +
|
| +
|
| +template <size_t signature_tag_size> struct FunctionTraits;
|
| +
|
| +
|
| +#define SIGNATURE_TRAITS(id, signature) \
|
| + SignatureTag<id> GetTag(signature); \
|
| + template <> struct FunctionTraits<sizeof(SignatureTag<id>)>
|
| +
|
| +SIGNATURE_TRAITS(1, Object* (*)(Arguments)) {
|
| + static const Runtime::CallingConvention conv = Runtime::EXIT_FRAME_CALL;
|
| +};
|
| +
|
| +
|
| +SIGNATURE_TRAITS(2, ObjectPair (*)(Arguments)) {
|
| + static const Runtime::CallingConvention conv = Runtime::EXIT_FRAME_CALL;
|
| +};
|
| +
|
| +
|
| +SIGNATURE_TRAITS(3, Object* (*)(Object* arg)) {
|
| + static const Runtime::CallingConvention conv = Runtime::DIRECT_CALL_NOT_FAILS;
|
| +};
|
| +
|
| +
|
| +SIGNATURE_TRAITS(4, Object* (*)(Object* agr0, Object* arg1)) {
|
| + static const Runtime::CallingConvention conv = Runtime::DIRECT_CALL_NOT_FAILS;
|
| +};
|
| +
|
| +SIGNATURE_TRAITS(5, Object* (*)(Object* arg0, Object* arg1, Object* arg2)) {
|
| + static const Runtime::CallingConvention conv = Runtime::DIRECT_CALL_NOT_FAILS;
|
| +};
|
| +}
|
| +
|
| // ----------------------------------------------------------------------------
|
| // Implementation of Runtime
|
|
|
| #define F(name, nargs, ressize) \
|
| { #name, FUNCTION_ADDR(Runtime_##name), nargs, \
|
| - static_cast<int>(Runtime::k##name), ressize },
|
| + static_cast<int>(Runtime::k##name), ressize, \
|
| + FunctionTraits<sizeof(GetTag(Runtime_##name))>::conv},
|
|
|
| static Runtime::Function Runtime_functions[] = {
|
| RUNTIME_FUNCTION_LIST(F)
|
| - { NULL, NULL, 0, -1, 0 }
|
| + { NULL, NULL, 0, -1, 0, Runtime::EXIT_FRAME_CALL }
|
| };
|
|
|
| #undef F
|
|
|