summaryrefslogtreecommitdiffstats
path: root/V8Binding/v8/src/runtime.cc
diff options
context:
space:
mode:
Diffstat (limited to 'V8Binding/v8/src/runtime.cc')
-rw-r--r--V8Binding/v8/src/runtime.cc223
1 files changed, 137 insertions, 86 deletions
diff --git a/V8Binding/v8/src/runtime.cc b/V8Binding/v8/src/runtime.cc
index c26783a..4e1940d 100644
--- a/V8Binding/v8/src/runtime.cc
+++ b/V8Binding/v8/src/runtime.cc
@@ -1208,6 +1208,14 @@ static Object* Runtime_FunctionIsAPIFunction(Arguments args) {
: Heap::false_value();
}
+static Object* Runtime_FunctionIsBuiltin(Arguments args) {
+ NoHandleAllocation ha;
+ ASSERT(args.length() == 1);
+
+ CONVERT_CHECKED(JSFunction, f, args[0]);
+ return f->IsBuiltin() ? Heap::true_value() : Heap::false_value();
+}
+
static Object* Runtime_SetCode(Arguments args) {
HandleScope scope;
@@ -2992,7 +3000,8 @@ static Object* Runtime_GetPropertyNamesFast(Arguments args) {
HandleScope scope;
Handle<JSObject> object(raw_object);
- Handle<FixedArray> content = GetKeysInFixedArrayFor(object);
+ Handle<FixedArray> content = GetKeysInFixedArrayFor(object,
+ INCLUDE_PROTOS);
// Test again, since cache may have been built by preceding call.
if (object->IsSimpleEnum()) return object->map();
@@ -3001,6 +3010,34 @@ static Object* Runtime_GetPropertyNamesFast(Arguments args) {
}
+static Object* Runtime_LocalKeys(Arguments args) {
+ ASSERT_EQ(args.length(), 1);
+ CONVERT_CHECKED(JSObject, raw_object, args[0]);
+ HandleScope scope;
+ Handle<JSObject> object(raw_object);
+ Handle<FixedArray> contents = GetKeysInFixedArrayFor(object,
+ LOCAL_ONLY);
+ // Some fast paths through GetKeysInFixedArrayFor reuse a cached
+ // property array and since the result is mutable we have to create
+ // a fresh clone on each invocation.
+ int length = contents->length();
+ Handle<FixedArray> copy = Factory::NewFixedArray(length);
+ for (int i = 0; i < length; i++) {
+ Object* entry = contents->get(i);
+ if (entry->IsString()) {
+ copy->set(i, entry);
+ } else {
+ ASSERT(entry->IsNumber());
+ HandleScope scope;
+ Handle<Object> entry_handle(entry);
+ Handle<Object> entry_str = Factory::NumberToString(entry_handle);
+ copy->set(i, *entry_str);
+ }
+ }
+ return *Factory::NewJSArrayWithElements(copy);
+}
+
+
static Object* Runtime_GetArgumentsProperty(Arguments args) {
NoHandleAllocation ha;
ASSERT(args.length() == 1);
@@ -3562,27 +3599,7 @@ static Object* Runtime_NumberToString(Arguments args) {
Object* number = args[0];
RUNTIME_ASSERT(number->IsNumber());
- Object* cached = Heap::GetNumberStringCache(number);
- if (cached != Heap::undefined_value()) {
- return cached;
- }
-
- char arr[100];
- Vector<char> buffer(arr, ARRAY_SIZE(arr));
- const char* str;
- if (number->IsSmi()) {
- int num = Smi::cast(number)->value();
- str = IntToCString(num, buffer);
- } else {
- double num = HeapNumber::cast(number)->value();
- str = DoubleToCString(num, buffer);
- }
- Object* result = Heap::AllocateStringFromAscii(CStrVector(str));
-
- if (!result->IsFailure()) {
- Heap::SetNumberStringCache(number, String::cast(result));
- }
- return result;
+ return Heap::NumberToString(number);
}
@@ -3696,7 +3713,7 @@ static Object* Runtime_NumberMod(Arguments args) {
CONVERT_DOUBLE_CHECKED(x, args[0]);
CONVERT_DOUBLE_CHECKED(y, args[1]);
-#ifdef WIN32
+#if defined WIN32 || defined _WIN64
// Workaround MS fmod bugs. ECMA-262 says:
// dividend is finite and divisor is an infinity => result equals dividend
// dividend is a zero and divisor is nonzero finite => result equals dividend
@@ -4556,22 +4573,25 @@ static Object* Runtime_LookupContext(Arguments args) {
}
-// A mechanism to return pairs of Object*'s. This is somewhat
-// compiler-dependent as it assumes that a 64-bit value (a long long)
-// is returned via two registers (edx:eax on ia32). Both the ia32 and
-// arm platform support this; it is mostly an issue of "coaxing" the
-// compiler to do the right thing.
-//
-// TODO(1236026): This is a non-portable hack that should be removed.
+// A mechanism to return a pair of Object pointers in registers (if possible).
+// How this is achieved is calling convention-dependent.
+// All currently supported x86 compiles uses calling conventions that are cdecl
+// variants where a 64-bit value is returned in two 32-bit registers
+// (edx:eax on ia32, r1:r0 on ARM).
+// In AMD-64 calling convention a struct of two pointers is returned in rdx:rax.
+// In Win64 calling convention, a struct of two pointers is returned in memory,
+// allocated by the caller, and passed as a pointer in a hidden first parameter.
#ifdef V8_HOST_ARCH_64_BIT
-// Tested with GCC, not with MSVC.
struct ObjectPair {
Object* x;
Object* y;
};
+
static inline ObjectPair MakePair(Object* x, Object* y) {
ObjectPair result = {x, y};
- return result; // Pointers x and y returned in rax and rdx, in AMD-x64-abi.
+ // Pointers x and y returned in rax and rdx, in AMD-x64-abi.
+ // In Win64 they are assigned to a hidden first argument.
+ return result;
}
#else
typedef uint64_t ObjectPair;
@@ -4582,8 +4602,6 @@ static inline ObjectPair MakePair(Object* x, Object* y) {
#endif
-
-
static inline Object* Unhole(Object* x, PropertyAttributes attributes) {
ASSERT(!x->IsTheHole() || (attributes & READ_ONLY) != 0);
USE(attributes);
@@ -5515,7 +5533,7 @@ static Object* Runtime_GetArrayKeys(Arguments args) {
if (array->elements()->IsDictionary()) {
// Create an array and get all the keys into it, then remove all the
// keys that are not integers in the range 0 to length-1.
- Handle<FixedArray> keys = GetKeysInFixedArrayFor(array);
+ Handle<FixedArray> keys = GetKeysInFixedArrayFor(array, INCLUDE_PROTOS);
int keys_length = keys->length();
for (int i = 0; i < keys_length; i++) {
Object* key = keys->get(i);
@@ -5737,55 +5755,51 @@ static Object* Runtime_DebugGetPropertyDetails(Arguments args) {
int length = LocalPrototypeChainLength(*obj);
// Try local lookup on each of the objects.
- LookupResult result;
Handle<JSObject> jsproto = obj;
for (int i = 0; i < length; i++) {
+ LookupResult result;
jsproto->LocalLookup(*name, &result);
if (result.IsProperty()) {
- break;
+ // LookupResult is not GC safe as it holds raw object pointers.
+ // GC can happen later in this code so put the required fields into
+ // local variables using handles when required for later use.
+ PropertyType result_type = result.type();
+ Handle<Object> result_callback_obj;
+ if (result_type == CALLBACKS) {
+ result_callback_obj = Handle<Object>(result.GetCallbackObject());
+ }
+ Smi* property_details = result.GetPropertyDetails().AsSmi();
+ // DebugLookupResultValue can cause GC so details from LookupResult needs
+ // to be copied to handles before this.
+ bool caught_exception = false;
+ Object* raw_value = DebugLookupResultValue(*obj, *name, &result,
+ &caught_exception);
+ if (raw_value->IsFailure()) return raw_value;
+ Handle<Object> value(raw_value);
+
+ // If the callback object is a fixed array then it contains JavaScript
+ // getter and/or setter.
+ bool hasJavaScriptAccessors = result_type == CALLBACKS &&
+ result_callback_obj->IsFixedArray();
+ Handle<FixedArray> details =
+ Factory::NewFixedArray(hasJavaScriptAccessors ? 5 : 2);
+ details->set(0, *value);
+ details->set(1, property_details);
+ if (hasJavaScriptAccessors) {
+ details->set(2,
+ caught_exception ? Heap::true_value()
+ : Heap::false_value());
+ details->set(3, FixedArray::cast(*result_callback_obj)->get(0));
+ details->set(4, FixedArray::cast(*result_callback_obj)->get(1));
+ }
+
+ return *Factory::NewJSArrayWithElements(details);
}
if (i < length - 1) {
jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype()));
}
}
- if (result.IsProperty()) {
- // LookupResult is not GC safe as all its members are raw object pointers.
- // When calling DebugLookupResultValue GC can happen as this might invoke
- // callbacks. After the call to DebugLookupResultValue the callback object
- // in the LookupResult might still be needed. Put it into a handle for later
- // use.
- PropertyType result_type = result.type();
- Handle<Object> result_callback_obj;
- if (result_type == CALLBACKS) {
- result_callback_obj = Handle<Object>(result.GetCallbackObject());
- }
-
- // Find the actual value. Don't use result after this call as it's content
- // can be invalid.
- bool caught_exception = false;
- Object* value = DebugLookupResultValue(*obj, *name, &result,
- &caught_exception);
- if (value->IsFailure()) return value;
- Handle<Object> value_handle(value);
-
- // If the callback object is a fixed array then it contains JavaScript
- // getter and/or setter.
- bool hasJavaScriptAccessors = result_type == CALLBACKS &&
- result_callback_obj->IsFixedArray();
- Handle<FixedArray> details =
- Factory::NewFixedArray(hasJavaScriptAccessors ? 5 : 2);
- details->set(0, *value_handle);
- details->set(1, result.GetPropertyDetails().AsSmi());
- if (hasJavaScriptAccessors) {
- details->set(2,
- caught_exception ? Heap::true_value() : Heap::false_value());
- details->set(3, FixedArray::cast(result.GetCallbackObject())->get(0));
- details->set(4, FixedArray::cast(result.GetCallbackObject())->get(1));
- }
-
- return *Factory::NewJSArrayWithElements(details);
- }
return Heap::undefined_value();
}
@@ -6270,7 +6284,7 @@ static Handle<JSObject> MaterializeLocalScope(JavaScriptFrame* frame) {
if (function_context->has_extension() &&
!function_context->IsGlobalContext()) {
Handle<JSObject> ext(JSObject::cast(function_context->extension()));
- Handle<FixedArray> keys = GetKeysInFixedArrayFor(ext);
+ Handle<FixedArray> keys = GetKeysInFixedArrayFor(ext, INCLUDE_PROTOS);
for (int i = 0; i < keys->length(); i++) {
// Names of variables introduced by eval are strings.
ASSERT(keys->get(i)->IsString());
@@ -6319,7 +6333,7 @@ static Handle<JSObject> MaterializeClosure(Handle<Context> context) {
// be variables introduced by eval.
if (context->has_extension()) {
Handle<JSObject> ext(JSObject::cast(context->extension()));
- Handle<FixedArray> keys = GetKeysInFixedArrayFor(ext);
+ Handle<FixedArray> keys = GetKeysInFixedArrayFor(ext, INCLUDE_PROTOS);
for (int i = 0; i < keys->length(); i++) {
// Names of variables introduced by eval are strings.
ASSERT(keys->get(i)->IsString());
@@ -6341,7 +6355,12 @@ class ScopeIterator {
ScopeTypeGlobal = 0,
ScopeTypeLocal,
ScopeTypeWith,
- ScopeTypeClosure
+ ScopeTypeClosure,
+ // Every catch block contains an implicit with block (its parameter is
+ // a JSContextExtensionObject) that extends current scope with a variable
+ // holding exception object. Such with blocks are treated as scopes of their
+ // own type.
+ ScopeTypeCatch
};
explicit ScopeIterator(JavaScriptFrame* frame)
@@ -6417,7 +6436,14 @@ class ScopeIterator {
return ScopeTypeClosure;
}
ASSERT(context_->has_extension());
- ASSERT(!context_->extension()->IsJSContextExtensionObject());
+ // Current scope is either an explicit with statement or a with statement
+ // implicitely generated for a catch block.
+ // If the extension object here is a JSContextExtensionObject then
+ // current with statement is one frome a catch block otherwise it's a
+ // regular with statement.
+ if (context_->extension()->IsJSContextExtensionObject()) {
+ return ScopeTypeCatch;
+ }
return ScopeTypeWith;
}
@@ -6432,6 +6458,7 @@ class ScopeIterator {
return MaterializeLocalScope(frame_);
break;
case ScopeIterator::ScopeTypeWith:
+ case ScopeIterator::ScopeTypeCatch:
// Return the with object.
return Handle<JSObject>(CurrentContext()->extension());
break;
@@ -6488,6 +6515,14 @@ class ScopeIterator {
break;
}
+ case ScopeIterator::ScopeTypeCatch: {
+ PrintF("Catch:\n");
+ Handle<JSObject> extension =
+ Handle<JSObject>(CurrentContext()->extension());
+ extension->Print();
+ break;
+ }
+
case ScopeIterator::ScopeTypeClosure: {
PrintF("Closure:\n");
CurrentContext()->Print();
@@ -6799,8 +6834,20 @@ Object* Runtime::FindSharedFunctionInfoInScript(Handle<Script> script,
target_start_position = start_position;
target = shared;
} else {
- if (target_start_position < start_position &&
- shared->end_position() < target->end_position()) {
+ if (target_start_position == start_position &&
+ shared->end_position() == target->end_position()) {
+ // If a top-level function contain only one function
+ // declartion the source for the top-level and the function is
+ // the same. In that case prefer the non top-level function.
+ if (!shared->is_toplevel()) {
+ target_start_position = start_position;
+ target = shared;
+ }
+ } else if (target_start_position <= start_position &&
+ shared->end_position() <= target->end_position()) {
+ // This containment check includes equality as a function inside
+ // a top-level function can share either start or end position
+ // with the top-level function.
target_start_position = start_position;
target = shared;
}
@@ -6912,7 +6959,8 @@ static Object* Runtime_ChangeBreakOnException(Arguments args) {
// Prepare for stepping
// args[0]: break id for checking execution state
// args[1]: step action from the enumeration StepAction
-// args[2]: number of times to perform the step
+// args[2]: number of times to perform the step, for step out it is the number
+// of frames to step down.
static Object* Runtime_PrepareStep(Arguments args) {
HandleScope scope;
ASSERT(args.length() == 3);
@@ -6939,6 +6987,9 @@ static Object* Runtime_PrepareStep(Arguments args) {
return Top::Throw(Heap::illegal_argument_symbol());
}
+ // Clear all current stepping setup.
+ Debug::ClearStepping();
+
// Prepare step.
Debug::PrepareStep(static_cast<StepAction>(step_action), step_count);
return Heap::undefined_value();
@@ -7089,7 +7140,7 @@ static Object* Runtime_DebugEvaluate(Arguments args) {
// the function being debugged.
// function(arguments,__source__) {return eval(__source__);}
static const char* source_str =
- "function(arguments,__source__){return eval(__source__);}";
+ "(function(arguments,__source__){return eval(__source__);})";
static const int source_str_length = strlen(source_str);
Handle<String> function_source =
Factory::NewStringFromAscii(Vector<const char>(source_str,
@@ -7598,7 +7649,7 @@ static Object* Runtime_ListNatives(Arguments args) {
HandleScope scope;
Handle<JSArray> result = Factory::NewJSArray(0);
int index = 0;
-#define ADD_ENTRY(Name, argc) \
+#define ADD_ENTRY(Name, argc, ressize) \
{ \
HandleScope inner; \
Handle<String> name = \
@@ -7634,13 +7685,13 @@ static Object* Runtime_IS_VAR(Arguments args) {
// ----------------------------------------------------------------------------
// Implementation of Runtime
-#define F(name, nargs) \
+#define F(name, nargs, ressize) \
{ #name, "RuntimeStub_" #name, FUNCTION_ADDR(Runtime_##name), nargs, \
- static_cast<int>(Runtime::k##name) },
+ static_cast<int>(Runtime::k##name), ressize },
static Runtime::Function Runtime_functions[] = {
RUNTIME_FUNCTION_LIST(F)
- { NULL, NULL, NULL, 0, -1 }
+ { NULL, NULL, NULL, 0, -1, 0 }
};
#undef F