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 |