Handlify the runtime lookup of CallIC and KeyedCallIC.

R=ulan@chromium.org
BUG=
TEST=

Review URL: http://codereview.chromium.org/8345038

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@9701 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
kmillikin@chromium.org 2011-10-19 12:04:16 +00:00
parent acc0263755
commit 838fc27766
13 changed files with 192 additions and 212 deletions

View File

@ -527,7 +527,9 @@ MaybeObject* Accessors::FunctionGetLength(Object* object, void*) {
// correctly yet. Compile it now and return the right length. // correctly yet. Compile it now and return the right length.
HandleScope scope; HandleScope scope;
Handle<JSFunction> handle(function); Handle<JSFunction> handle(function);
if (!CompileLazy(handle, KEEP_EXCEPTION)) return Failure::Exception(); if (!JSFunction::CompileLazy(handle, KEEP_EXCEPTION)) {
return Failure::Exception();
}
return Smi::FromInt(handle->shared()->length()); return Smi::FromInt(handle->shared()->length());
} else { } else {
return Smi::FromInt(function->shared()->length()); return Smi::FromInt(function->shared()->length());

View File

@ -2794,7 +2794,7 @@ Local<Value> v8::Object::Get(uint32_t index) {
ENTER_V8(isolate); ENTER_V8(isolate);
i::Handle<i::JSObject> self = Utils::OpenHandle(this); i::Handle<i::JSObject> self = Utils::OpenHandle(this);
EXCEPTION_PREAMBLE(isolate); EXCEPTION_PREAMBLE(isolate);
i::Handle<i::Object> result = i::GetElement(self, index); i::Handle<i::Object> result = i::Object::GetElement(self, index);
has_pending_exception = result.is_null(); has_pending_exception = result.is_null();
EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>()); EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>());
return Utils::ToLocal(result); return Utils::ToLocal(result);
@ -3093,13 +3093,10 @@ static Local<Value> GetPropertyByLookup(i::Isolate* isolate,
// If the property being looked up is a callback, it can throw // If the property being looked up is a callback, it can throw
// an exception. // an exception.
EXCEPTION_PREAMBLE(isolate); EXCEPTION_PREAMBLE(isolate);
PropertyAttributes attributes; PropertyAttributes ignored;
i::Handle<i::Object> result = i::Object::GetProperty(isolate, i::Handle<i::Object> result =
receiver, i::Object::GetProperty(receiver, receiver, lookup, name,
receiver, &ignored);
lookup,
name,
&attributes);
has_pending_exception = result.is_null(); has_pending_exception = result.is_null();
EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>()); EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>());

View File

@ -2007,7 +2007,9 @@ bool Genesis::InstallJSBuiltins(Handle<JSBuiltinsObject> builtins) {
builtins->set_javascript_builtin(id, *function); builtins->set_javascript_builtin(id, *function);
Handle<SharedFunctionInfo> shared Handle<SharedFunctionInfo> shared
= Handle<SharedFunctionInfo>(function->shared()); = Handle<SharedFunctionInfo>(function->shared());
if (!EnsureCompiled(shared, CLEAR_EXCEPTION)) return false; if (!SharedFunctionInfo::EnsureCompiled(shared, CLEAR_EXCEPTION)) {
return false;
}
// Set the code object on the function object. // Set the code object on the function object.
function->ReplaceCode(function->shared()->code()); function->ReplaceCode(function->shared()->code());
builtins->set_javascript_builtin_code(id, shared->code()); builtins->set_javascript_builtin_code(id, shared->code());

View File

@ -1940,7 +1940,9 @@ bool Debug::EnsureDebugInfo(Handle<SharedFunctionInfo> shared) {
} }
// Ensure shared in compiled. Return false if this failed. // Ensure shared in compiled. Return false if this failed.
if (!EnsureCompiled(shared, CLEAR_EXCEPTION)) return false; if (!SharedFunctionInfo::EnsureCompiled(shared, CLEAR_EXCEPTION)) {
return false;
}
// Create the debug info object. // Create the debug info object.
Handle<DebugInfo> debug_info = FACTORY->NewDebugInfo(shared); Handle<DebugInfo> debug_info = FACTORY->NewDebugInfo(shared);

View File

@ -376,13 +376,6 @@ Handle<Object> GetProperty(Handle<Object> obj,
} }
Handle<Object> GetElement(Handle<Object> obj,
uint32_t index) {
Isolate* isolate = Isolate::Current();
CALL_HEAP_FUNCTION(isolate, Runtime::GetElement(obj, index), Object);
}
Handle<Object> GetPropertyWithInterceptor(Handle<JSObject> receiver, Handle<Object> GetPropertyWithInterceptor(Handle<JSObject> receiver,
Handle<JSObject> holder, Handle<JSObject> holder,
Handle<String> name, Handle<String> name,
@ -888,53 +881,4 @@ Handle<ObjectHashTable> PutIntoObjectHashTable(Handle<ObjectHashTable> table,
} }
bool EnsureCompiled(Handle<SharedFunctionInfo> shared,
ClearExceptionFlag flag) {
return shared->is_compiled() || CompileLazyShared(shared, flag);
}
static bool CompileLazyHelper(CompilationInfo* info,
ClearExceptionFlag flag) {
// Compile the source information to a code object.
ASSERT(info->IsOptimizing() || !info->shared_info()->is_compiled());
ASSERT(!info->isolate()->has_pending_exception());
bool result = Compiler::CompileLazy(info);
ASSERT(result != Isolate::Current()->has_pending_exception());
if (!result && flag == CLEAR_EXCEPTION) {
info->isolate()->clear_pending_exception();
}
return result;
}
bool CompileLazyShared(Handle<SharedFunctionInfo> shared,
ClearExceptionFlag flag) {
CompilationInfo info(shared);
return CompileLazyHelper(&info, flag);
}
bool CompileLazy(Handle<JSFunction> function, ClearExceptionFlag flag) {
bool result = true;
if (function->shared()->is_compiled()) {
function->ReplaceCode(function->shared()->code());
function->shared()->set_code_age(0);
} else {
CompilationInfo info(function);
result = CompileLazyHelper(&info, flag);
ASSERT(!result || function->is_compiled());
}
return result;
}
bool CompileOptimized(Handle<JSFunction> function,
int osr_ast_id,
ClearExceptionFlag flag) {
CompilationInfo info(function);
info.SetOptimizing(osr_ast_id);
return CompileLazyHelper(&info, flag);
}
} } // namespace v8::internal } } // namespace v8::internal

View File

@ -246,9 +246,6 @@ Handle<Object> GetProperty(Handle<JSReceiver> obj,
Handle<Object> GetProperty(Handle<Object> obj, Handle<Object> GetProperty(Handle<Object> obj,
Handle<Object> key); Handle<Object> key);
Handle<Object> GetElement(Handle<Object> obj,
uint32_t index);
Handle<Object> GetPropertyWithInterceptor(Handle<JSObject> receiver, Handle<Object> GetPropertyWithInterceptor(Handle<JSObject> receiver,
Handle<JSObject> holder, Handle<JSObject> holder,
Handle<String> name, Handle<String> name,
@ -345,22 +342,6 @@ Handle<ObjectHashTable> PutIntoObjectHashTable(Handle<ObjectHashTable> table,
Handle<JSReceiver> key, Handle<JSReceiver> key,
Handle<Object> value); Handle<Object> value);
// Does lazy compilation of the given function. Returns true on success and
// false if the compilation resulted in a stack overflow.
enum ClearExceptionFlag { KEEP_EXCEPTION, CLEAR_EXCEPTION };
bool EnsureCompiled(Handle<SharedFunctionInfo> shared,
ClearExceptionFlag flag);
bool CompileLazyShared(Handle<SharedFunctionInfo> shared,
ClearExceptionFlag flag);
bool CompileLazy(Handle<JSFunction> function, ClearExceptionFlag flag);
bool CompileOptimized(Handle<JSFunction> function,
int osr_ast_id,
ClearExceptionFlag flag);
class NoHandleAllocation BASE_EMBEDDED { class NoHandleAllocation BASE_EMBEDDED {
public: public:
#ifndef DEBUG #ifndef DEBUG

151
src/ic.cc
View File

@ -445,23 +445,20 @@ static void LookupForRead(Handle<Object> object,
} }
Object* CallICBase::TryCallAsFunction(Object* object) { Handle<Object> CallICBase::TryCallAsFunction(Handle<Object> object) {
HandleScope scope(isolate()); Handle<Object> delegate = Execution::GetFunctionDelegate(object);
Handle<Object> target(object, isolate());
Handle<Object> delegate = Execution::GetFunctionDelegate(target);
if (delegate->IsJSFunction() && !object->IsJSFunctionProxy()) { if (delegate->IsJSFunction() && !object->IsJSFunctionProxy()) {
// Patch the receiver and use the delegate as the function to // Patch the receiver and use the delegate as the function to
// invoke. This is used for invoking objects as if they were // invoke. This is used for invoking objects as if they were functions.
// functions. const int argc = target()->arguments_count();
const int argc = this->target()->arguments_count();
StackFrameLocator locator; StackFrameLocator locator;
JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
int index = frame->ComputeExpressionsCount() - (argc + 1); int index = frame->ComputeExpressionsCount() - (argc + 1);
frame->SetExpression(index, *target); frame->SetExpression(index, *object);
} }
return *delegate; return delegate;
} }
@ -505,31 +502,27 @@ MaybeObject* CallICBase::LoadFunction(State state,
// the element if so. // the element if so.
uint32_t index; uint32_t index;
if (name->AsArrayIndex(&index)) { if (name->AsArrayIndex(&index)) {
Object* result; Handle<Object> result = Object::GetElement(object, index);
{ MaybeObject* maybe_result = object->GetElement(index); RETURN_IF_EMPTY_HANDLE(isolate(), result);
if (!maybe_result->ToObject(&result)) return maybe_result; if (result->IsJSFunction()) return *result;
}
if (result->IsJSFunction()) return result;
// Try to find a suitable function delegate for the object at hand. // Try to find a suitable function delegate for the object at hand.
result = TryCallAsFunction(result); result = TryCallAsFunction(result);
if (result->IsJSFunction()) return result; if (result->IsJSFunction()) return *result;
// Otherwise, it will fail in the lookup step. // Otherwise, it will fail in the lookup step.
} }
// Lookup the property in the object. // Lookup the property in the object.
LookupResult lookup(isolate()); LookupResult lookup(isolate());
LookupForRead(*object, *name, &lookup); LookupForRead(object, name, &lookup);
if (!lookup.IsProperty()) { if (!lookup.IsProperty()) {
// If the object does not have the requested property, check which // If the object does not have the requested property, check which
// exception we need to throw. // exception we need to throw.
if (IsContextual(object)) { return IsContextual(object)
return ReferenceError("not_defined", name); ? ReferenceError("not_defined", name)
} : TypeError("undefined_method", object, name);
return TypeError("undefined_method", object, name);
} }
// Lookup is valid: Update inline cache and stub cache. // Lookup is valid: Update inline cache and stub cache.
@ -539,53 +532,42 @@ MaybeObject* CallICBase::LoadFunction(State state,
// Get the property. // Get the property.
PropertyAttributes attr; PropertyAttributes attr;
Object* result; Handle<Object> result =
{ MaybeObject* maybe_result = Object::GetProperty(object, object, &lookup, name, &attr);
object->GetProperty(*object, &lookup, *name, &attr); RETURN_IF_EMPTY_HANDLE(isolate(), result);
if (!maybe_result->ToObject(&result)) return maybe_result;
}
if (lookup.type() == INTERCEPTOR) { if (lookup.type() == INTERCEPTOR && attr == ABSENT) {
// If the object does not have the requested property, check which // If the object does not have the requested property, check which
// exception we need to throw. // exception we need to throw.
if (attr == ABSENT) { return IsContextual(object)
if (IsContextual(object)) { ? ReferenceError("not_defined", name)
return ReferenceError("not_defined", name); : TypeError("undefined_method", object, name);
}
return TypeError("undefined_method", object, name);
}
} }
ASSERT(!result->IsTheHole()); ASSERT(!result->IsTheHole());
HandleScope scope(isolate());
// Wrap result in a handle because ReceiverToObjectIfRequired may allocate
// new object and cause GC.
Handle<Object> result_handle(result);
// Make receiver an object if the callee requires it. Strict mode or builtin // Make receiver an object if the callee requires it. Strict mode or builtin
// functions do not wrap the receiver, non-strict functions and objects // functions do not wrap the receiver, non-strict functions and objects
// called as functions do. // called as functions do.
ReceiverToObjectIfRequired(result_handle, object); ReceiverToObjectIfRequired(result, object);
if (result_handle->IsJSFunction()) { if (result->IsJSFunction()) {
Handle<JSFunction> function = Handle<JSFunction>::cast(result);
#ifdef ENABLE_DEBUGGER_SUPPORT #ifdef ENABLE_DEBUGGER_SUPPORT
// Handle stepping into a function if step into is active. // Handle stepping into a function if step into is active.
Debug* debug = isolate()->debug(); Debug* debug = isolate()->debug();
if (debug->StepInActive()) { if (debug->StepInActive()) {
// Protect the result in a handle as the debugger can allocate and might // Protect the result in a handle as the debugger can allocate and might
// cause GC. // cause GC.
Handle<JSFunction> function(JSFunction::cast(*result_handle), isolate());
debug->HandleStepIn(function, object, fp(), false); debug->HandleStepIn(function, object, fp(), false);
return *function;
} }
#endif #endif
return *function;
return *result_handle;
} }
// Try to find a suitable function delegate for the object at hand. // Try to find a suitable function delegate for the object at hand.
result_handle = Handle<Object>(TryCallAsFunction(*result_handle)); result = TryCallAsFunction(result);
if (result_handle->IsJSFunction()) return *result_handle; if (result->IsJSFunction()) return *result;
return TypeError("property_not_function", object, name); return TypeError("property_not_function", object, name);
} }
@ -827,26 +809,25 @@ MaybeObject* KeyedCallIC::LoadFunction(State state,
if (FLAG_use_ic && state != MEGAMORPHIC && object->IsHeapObject()) { if (FLAG_use_ic && state != MEGAMORPHIC && object->IsHeapObject()) {
int argc = target()->arguments_count(); int argc = target()->arguments_count();
Heap* heap = Handle<HeapObject>::cast(object)->GetHeap(); Handle<Map> map =
Map* map = heap->non_strict_arguments_elements_map(); isolate()->factory()->non_strict_arguments_elements_map();
if (object->IsJSObject() && if (object->IsJSObject() &&
Handle<JSObject>::cast(object)->elements()->map() == map) { Handle<JSObject>::cast(object)->elements()->map() == *map) {
MaybeObject* maybe_code = isolate()->stub_cache()->ComputeCallArguments( MaybeObject* maybe_code = isolate()->stub_cache()->ComputeCallArguments(
argc, Code::KEYED_CALL_IC); argc, Code::KEYED_CALL_IC);
Object* code; Code* code = NULL;
if (maybe_code->ToObject(&code)) { if (maybe_code->To(&code)) {
set_target(Code::cast(code)); set_target(code);
#ifdef DEBUG #ifdef DEBUG
TraceIC("KeyedCallIC", key, state, target()); TraceIC("KeyedCallIC", key, state, target());
#endif #endif
} }
} else if (FLAG_use_ic && state != MEGAMORPHIC && } else if (!object->IsAccessCheckNeeded()) {
!object->IsAccessCheckNeeded()) {
MaybeObject* maybe_code = isolate()->stub_cache()->ComputeCallMegamorphic( MaybeObject* maybe_code = isolate()->stub_cache()->ComputeCallMegamorphic(
argc, Code::KEYED_CALL_IC, Code::kNoExtraICState); argc, Code::KEYED_CALL_IC, Code::kNoExtraICState);
Object* code; Code* code;
if (maybe_code->ToObject(&code)) { if (maybe_code->To(&code)) {
set_target(Code::cast(code)); set_target(code);
#ifdef DEBUG #ifdef DEBUG
TraceIC("KeyedCallIC", key, state, target()); TraceIC("KeyedCallIC", key, state, target());
#endif #endif
@ -854,7 +835,6 @@ MaybeObject* KeyedCallIC::LoadFunction(State state,
} }
} }
HandleScope scope(isolate());
Handle<Object> result = GetProperty(object, key); Handle<Object> result = GetProperty(object, key);
RETURN_IF_EMPTY_HANDLE(isolate(), result); RETURN_IF_EMPTY_HANDLE(isolate(), result);
@ -862,9 +842,9 @@ MaybeObject* KeyedCallIC::LoadFunction(State state,
// functions do not wrap the receiver, non-strict functions and objects // functions do not wrap the receiver, non-strict functions and objects
// called as functions do. // called as functions do.
ReceiverToObjectIfRequired(result, object); ReceiverToObjectIfRequired(result, object);
if (result->IsJSFunction()) return *result; if (result->IsJSFunction()) return *result;
result = Handle<Object>(TryCallAsFunction(*result));
result = TryCallAsFunction(result);
if (result->IsJSFunction()) return *result; if (result->IsJSFunction()) return *result;
return TypeError("property_not_function", object, key); return TypeError("property_not_function", object, key);
@ -981,7 +961,7 @@ MaybeObject* LoadIC::Load(State state,
(lookup.type() == INTERCEPTOR || lookup.type() == HANDLER)) { (lookup.type() == INTERCEPTOR || lookup.type() == HANDLER)) {
// Get the property. // Get the property.
Handle<Object> result = Handle<Object> result =
Object::GetProperty(isolate(), object, object, &lookup, name, &attr); Object::GetProperty(object, object, &lookup, name, &attr);
RETURN_IF_EMPTY_HANDLE(isolate(), result); RETURN_IF_EMPTY_HANDLE(isolate(), result);
// If the property is not present, check if we need to throw an // If the property is not present, check if we need to throw an
// exception. // exception.
@ -1996,19 +1976,9 @@ void KeyedStoreIC::UpdateCaches(LookupResult* lookup,
// Static IC stub generators. // Static IC stub generators.
// //
static JSFunction* CompileFunction(Isolate* isolate,
JSFunction* function) {
// Compile now with optimization.
HandleScope scope(isolate);
Handle<JSFunction> function_handle(function, isolate);
CompileLazy(function_handle, CLEAR_EXCEPTION);
return *function_handle;
}
// Used from ic-<arch>.cc. // Used from ic-<arch>.cc.
RUNTIME_FUNCTION(MaybeObject*, CallIC_Miss) { RUNTIME_FUNCTION(MaybeObject*, CallIC_Miss) {
NoHandleAllocation na; HandleScope scope(isolate);
ASSERT(args.length() == 2); ASSERT(args.length() == 2);
CallIC ic(isolate); CallIC ic(isolate);
IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
@ -2017,39 +1987,40 @@ RUNTIME_FUNCTION(MaybeObject*, CallIC_Miss) {
extra_ic_state, extra_ic_state,
args.at<Object>(0), args.at<Object>(0),
args.at<String>(1)); args.at<String>(1));
Object* result; // Result could be a function or a failure.
if (!maybe_result->ToObject(&result)) return maybe_result; JSFunction* raw_function = NULL;
if (!maybe_result->To(&raw_function)) return maybe_result;
// The first time the inline cache is updated may be the first time the // The first time the inline cache is updated may be the first time the
// function it references gets called. If the function was lazily compiled // function it references gets called. If the function is lazily compiled
// then the first call will trigger a compilation. We check for this case // then the first call will trigger a compilation. We check for this case
// and we do the compilation immediately, instead of waiting for the stub // and we do the compilation immediately, instead of waiting for the stub
// currently attached to the JSFunction object to trigger compilation. We // currently attached to the JSFunction object to trigger compilation.
// do this in the case where we know that the inline cache is inside a loop, if (raw_function->is_compiled()) return raw_function;
// because then we know that we want to optimize the function.
if (!result->IsJSFunction() || JSFunction::cast(result)->is_compiled()) { Handle<JSFunction> function(raw_function);
return result; JSFunction::CompileLazy(function, CLEAR_EXCEPTION);
} return *function;
return CompileFunction(isolate, JSFunction::cast(result));
} }
// Used from ic-<arch>.cc. // Used from ic-<arch>.cc.
RUNTIME_FUNCTION(MaybeObject*, KeyedCallIC_Miss) { RUNTIME_FUNCTION(MaybeObject*, KeyedCallIC_Miss) {
NoHandleAllocation na; HandleScope scope(isolate);
ASSERT(args.length() == 2); ASSERT(args.length() == 2);
KeyedCallIC ic(isolate); KeyedCallIC ic(isolate);
IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
Object* result; MaybeObject* maybe_result =
{ MaybeObject* maybe_result =
ic.LoadFunction(state, args.at<Object>(0), args.at<Object>(1)); ic.LoadFunction(state, args.at<Object>(0), args.at<Object>(1));
if (!maybe_result->ToObject(&result)) return maybe_result; // Result could be a function or a failure.
} JSFunction* raw_function = NULL;
if (!maybe_result->To(&raw_function)) return maybe_result;
if (!result->IsJSFunction() || JSFunction::cast(result)->is_compiled()) { if (raw_function->is_compiled()) return raw_function;
return result;
} Handle<JSFunction> function(raw_function);
return CompileFunction(isolate, JSFunction::cast(result)); JSFunction::CompileLazy(function, CLEAR_EXCEPTION);
return *function;
} }

View File

@ -203,6 +203,7 @@ class CallICBase: public IC {
: IC(EXTRA_CALL_FRAME, isolate), kind_(kind) {} : IC(EXTRA_CALL_FRAME, isolate), kind_(kind) {}
public: public:
// Returns a JSFunction or a Failure.
MUST_USE_RESULT MaybeObject* LoadFunction(State state, MUST_USE_RESULT MaybeObject* LoadFunction(State state,
Code::ExtraICState extra_ic_state, Code::ExtraICState extra_ic_state,
Handle<Object> object, Handle<Object> object,
@ -222,18 +223,18 @@ class CallICBase: public IC {
Handle<Object> object, Handle<Object> object,
Handle<String> name); Handle<String> name);
// Update the inline cache and the global stub cache based on the // Update the inline cache and the global stub cache based on the lookup
// lookup result. // result.
void UpdateCaches(LookupResult* lookup, void UpdateCaches(LookupResult* lookup,
State state, State state,
Code::ExtraICState extra_ic_state, Code::ExtraICState extra_ic_state,
Handle<Object> object, Handle<Object> object,
Handle<String> name); Handle<String> name);
// Returns a JSFunction if the object can be called as a function, // Returns a JSFunction if the object can be called as a function, and
// and patches the stack to be ready for the call. // patches the stack to be ready for the call. Otherwise, it returns the
// Otherwise, it returns the undefined value. // undefined value.
Object* TryCallAsFunction(Object* object); Handle<Object> TryCallAsFunction(Handle<Object> object);
void ReceiverToObjectIfRequired(Handle<Object> callee, Handle<Object> object); void ReceiverToObjectIfRequired(Handle<Object> callee, Handle<Object> object);

View File

@ -234,6 +234,14 @@ MaybeObject* JSProxy::GetPropertyWithHandler(Object* receiver_raw,
} }
Handle<Object> Object::GetElement(Handle<Object> object, uint32_t index) {
Isolate* isolate = object->IsHeapObject()
? Handle<HeapObject>::cast(object)->GetIsolate()
: Isolate::Current();
CALL_HEAP_FUNCTION(isolate, object->GetElement(index), Object);
}
MaybeObject* JSProxy::GetElementWithHandler(Object* receiver, MaybeObject* JSProxy::GetElementWithHandler(Object* receiver,
uint32_t index) { uint32_t index) {
String* name; String* name;
@ -528,12 +536,14 @@ bool JSObject::IsDirty() {
} }
Handle<Object> Object::GetProperty(Isolate* isolate, Handle<Object> Object::GetProperty(Handle<Object> object,
Handle<Object> object,
Handle<Object> receiver, Handle<Object> receiver,
LookupResult* result, LookupResult* result,
Handle<String> key, Handle<String> key,
PropertyAttributes* attributes) { PropertyAttributes* attributes) {
Isolate* isolate = object->IsHeapObject()
? Handle<HeapObject>::cast(object)->GetIsolate()
: Isolate::Current();
CALL_HEAP_FUNCTION( CALL_HEAP_FUNCTION(
isolate, isolate,
object->GetProperty(*receiver, result, *key, attributes), object->GetProperty(*receiver, result, *key, attributes),
@ -6941,6 +6951,57 @@ void JSFunction::MarkForLazyRecompilation() {
} }
bool SharedFunctionInfo::EnsureCompiled(Handle<SharedFunctionInfo> shared,
ClearExceptionFlag flag) {
return shared->is_compiled() || CompileLazy(shared, flag);
}
static bool CompileLazyHelper(CompilationInfo* info,
ClearExceptionFlag flag) {
// Compile the source information to a code object.
ASSERT(info->IsOptimizing() || !info->shared_info()->is_compiled());
ASSERT(!info->isolate()->has_pending_exception());
bool result = Compiler::CompileLazy(info);
ASSERT(result != Isolate::Current()->has_pending_exception());
if (!result && flag == CLEAR_EXCEPTION) {
info->isolate()->clear_pending_exception();
}
return result;
}
bool SharedFunctionInfo::CompileLazy(Handle<SharedFunctionInfo> shared,
ClearExceptionFlag flag) {
CompilationInfo info(shared);
return CompileLazyHelper(&info, flag);
}
bool JSFunction::CompileLazy(Handle<JSFunction> function,
ClearExceptionFlag flag) {
bool result = true;
if (function->shared()->is_compiled()) {
function->ReplaceCode(function->shared()->code());
function->shared()->set_code_age(0);
} else {
CompilationInfo info(function);
result = CompileLazyHelper(&info, flag);
ASSERT(!result || function->is_compiled());
}
return result;
}
bool JSFunction::CompileOptimized(Handle<JSFunction> function,
int osr_ast_id,
ClearExceptionFlag flag) {
CompilationInfo info(function);
info.SetOptimizing(osr_ast_id);
return CompileLazyHelper(&info, flag);
}
bool JSFunction::IsInlineable() { bool JSFunction::IsInlineable() {
if (IsBuiltin()) return false; if (IsBuiltin()) return false;
SharedFunctionInfo* shared_info = shared(); SharedFunctionInfo* shared_info = shared();

View File

@ -913,8 +913,7 @@ class Object : public MaybeObject {
String* key, String* key,
PropertyAttributes* attributes); PropertyAttributes* attributes);
static Handle<Object> GetProperty(Isolate* isolate, static Handle<Object> GetProperty(Handle<Object> object,
Handle<Object> object,
Handle<Object> receiver, Handle<Object> receiver,
LookupResult* result, LookupResult* result,
Handle<String> key, Handle<String> key,
@ -928,6 +927,7 @@ class Object : public MaybeObject {
MUST_USE_RESULT MaybeObject* GetPropertyWithDefinedGetter(Object* receiver, MUST_USE_RESULT MaybeObject* GetPropertyWithDefinedGetter(Object* receiver,
JSReceiver* getter); JSReceiver* getter);
static Handle<Object> GetElement(Handle<Object> object, uint32_t index);
inline MaybeObject* GetElement(uint32_t index); inline MaybeObject* GetElement(uint32_t index);
// For use when we know that no exception can be thrown. // For use when we know that no exception can be thrown.
inline Object* GetElementNoExceptionThrown(uint32_t index); inline Object* GetElementNoExceptionThrown(uint32_t index);
@ -4917,6 +4917,13 @@ class SharedFunctionInfo: public HeapObject {
void SharedFunctionInfoVerify(); void SharedFunctionInfoVerify();
#endif #endif
// Helpers to compile the shared code. Returns true on success, false on
// failure (e.g., stack overflow during compilation).
static bool EnsureCompiled(Handle<SharedFunctionInfo> shared,
ClearExceptionFlag flag);
static bool CompileLazy(Handle<SharedFunctionInfo> shared,
ClearExceptionFlag flag);
// Casting. // Casting.
static inline SharedFunctionInfo* cast(Object* obj); static inline SharedFunctionInfo* cast(Object* obj);
@ -5138,6 +5145,14 @@ class JSFunction: public JSObject {
// recompiled the next time it is executed. // recompiled the next time it is executed.
void MarkForLazyRecompilation(); void MarkForLazyRecompilation();
// Helpers to compile this function. Returns true on success, false on
// failure (e.g., stack overflow during compilation).
static bool CompileLazy(Handle<JSFunction> function,
ClearExceptionFlag flag);
static bool CompileOptimized(Handle<JSFunction> function,
int osr_ast_id,
ClearExceptionFlag flag);
// Tells whether or not the function is already marked for lazy // Tells whether or not the function is already marked for lazy
// recompilation. // recompilation.
inline bool IsMarkedForLazyRecompilation(); inline bool IsMarkedForLazyRecompilation();

View File

@ -1005,7 +1005,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOwnProperty) {
case JSObject::INTERCEPTED_ELEMENT: case JSObject::INTERCEPTED_ELEMENT:
case JSObject::FAST_ELEMENT: { case JSObject::FAST_ELEMENT: {
elms->set(IS_ACCESSOR_INDEX, heap->false_value()); elms->set(IS_ACCESSOR_INDEX, heap->false_value());
Handle<Object> value = GetElement(obj, index); Handle<Object> value = Object::GetElement(obj, index);
RETURN_IF_EMPTY_HANDLE(isolate, value); RETURN_IF_EMPTY_HANDLE(isolate, value);
elms->set(VALUE_INDEX, *value); elms->set(VALUE_INDEX, *value);
elms->set(WRITABLE_INDEX, heap->true_value()); elms->set(WRITABLE_INDEX, heap->true_value());
@ -1049,7 +1049,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOwnProperty) {
case NORMAL: { case NORMAL: {
// This is a data property. // This is a data property.
elms->set(IS_ACCESSOR_INDEX, heap->false_value()); elms->set(IS_ACCESSOR_INDEX, heap->false_value());
Handle<Object> value = GetElement(obj, index); Handle<Object> value = Object::GetElement(obj, index);
ASSERT(!value.is_null()); ASSERT(!value.is_null());
elms->set(VALUE_INDEX, *value); elms->set(VALUE_INDEX, *value);
elms->set(WRITABLE_INDEX, heap->ToBoolean(!details.IsReadOnly())); elms->set(WRITABLE_INDEX, heap->ToBoolean(!details.IsReadOnly()));
@ -2110,7 +2110,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_SetCode) {
Handle<JSFunction> fun = Handle<JSFunction>::cast(code); Handle<JSFunction> fun = Handle<JSFunction>::cast(code);
Handle<SharedFunctionInfo> shared(fun->shared()); Handle<SharedFunctionInfo> shared(fun->shared());
if (!EnsureCompiled(shared, KEEP_EXCEPTION)) { if (!SharedFunctionInfo::EnsureCompiled(shared, KEEP_EXCEPTION)) {
return Failure::Exception(); return Failure::Exception();
} }
// Since we don't store the source for this we should never // Since we don't store the source for this we should never
@ -4042,11 +4042,6 @@ MaybeObject* Runtime::GetElementOrCharAt(Isolate* isolate,
return prototype->GetElement(index); return prototype->GetElement(index);
} }
return GetElement(object, index);
}
MaybeObject* Runtime::GetElement(Handle<Object> object, uint32_t index) {
return object->GetElement(index); return object->GetElement(index);
} }
@ -8141,9 +8136,11 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_NewObject) {
// available. We cannot use EnsureCompiled because that forces a // available. We cannot use EnsureCompiled because that forces a
// compilation through the shared function info which makes it // compilation through the shared function info which makes it
// impossible for us to optimize. // impossible for us to optimize.
Handle<SharedFunctionInfo> shared(function->shared(), isolate); if (!function->is_compiled()) {
if (!function->is_compiled()) CompileLazy(function, CLEAR_EXCEPTION); JSFunction::CompileLazy(function, CLEAR_EXCEPTION);
}
Handle<SharedFunctionInfo> shared(function->shared(), isolate);
if (!function->has_initial_map() && if (!function->has_initial_map() &&
shared->IsInobjectSlackTrackingInProgress()) { shared->IsInobjectSlackTrackingInProgress()) {
// The tracking is already in progress for another function. We can only // The tracking is already in progress for another function. We can only
@ -8194,7 +8191,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_LazyCompile) {
// Compile the target function. // Compile the target function.
ASSERT(!function->is_compiled()); ASSERT(!function->is_compiled());
if (!CompileLazy(function, KEEP_EXCEPTION)) { if (!JSFunction::CompileLazy(function, KEEP_EXCEPTION)) {
return Failure::Exception(); return Failure::Exception();
} }
@ -8231,7 +8228,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_LazyRecompile) {
function->ReplaceCode(function->shared()->code()); function->ReplaceCode(function->shared()->code());
return function->code(); return function->code();
} }
if (CompileOptimized(function, AstNode::kNoNumber, CLEAR_EXCEPTION)) { if (JSFunction::CompileOptimized(function,
AstNode::kNoNumber,
CLEAR_EXCEPTION)) {
return function->code(); return function->code();
} }
if (FLAG_trace_opt) { if (FLAG_trace_opt) {
@ -8472,7 +8471,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileForOnStackReplacement) {
// Try to compile the optimized code. A true return value from // Try to compile the optimized code. A true return value from
// CompileOptimized means that compilation succeeded, not necessarily // CompileOptimized means that compilation succeeded, not necessarily
// that optimization succeeded. // that optimization succeeded.
if (CompileOptimized(function, ast_id, CLEAR_EXCEPTION) && if (JSFunction::CompileOptimized(function, ast_id, CLEAR_EXCEPTION) &&
function->IsOptimized()) { function->IsOptimized()) {
DeoptimizationInputData* data = DeoptimizationInputData::cast( DeoptimizationInputData* data = DeoptimizationInputData::cast(
function->code()->deoptimization_data()); function->code()->deoptimization_data());
@ -9847,8 +9846,8 @@ static bool IterateElements(Isolate* isolate,
} else if (receiver->HasElement(j)) { } else if (receiver->HasElement(j)) {
// Call GetElement on receiver, not its prototype, or getters won't // Call GetElement on receiver, not its prototype, or getters won't
// have the correct receiver. // have the correct receiver.
element_value = GetElement(receiver, j); element_value = Object::GetElement(receiver, j);
if (element_value.is_null()) return false; RETURN_IF_EMPTY_HANDLE_VALUE(isolate, element_value, false);
visitor->visit(j, element_value); visitor->visit(j, element_value);
} }
} }
@ -9866,8 +9865,8 @@ static bool IterateElements(Isolate* isolate,
while (j < n) { while (j < n) {
HandleScope loop_scope; HandleScope loop_scope;
uint32_t index = indices[j]; uint32_t index = indices[j];
Handle<Object> element = GetElement(receiver, index); Handle<Object> element = Object::GetElement(receiver, index);
if (element.is_null()) return false; RETURN_IF_EMPTY_HANDLE_VALUE(isolate, element, false);
visitor->visit(index, element); visitor->visit(index, element);
// Skip to next different index (i.e., omit duplicates). // Skip to next different index (i.e., omit duplicates).
do { do {
@ -10117,9 +10116,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_SwapElements) {
} }
Handle<JSObject> jsobject = Handle<JSObject>::cast(object); Handle<JSObject> jsobject = Handle<JSObject>::cast(object);
Handle<Object> tmp1 = GetElement(jsobject, index1); Handle<Object> tmp1 = Object::GetElement(jsobject, index1);
RETURN_IF_EMPTY_HANDLE(isolate, tmp1); RETURN_IF_EMPTY_HANDLE(isolate, tmp1);
Handle<Object> tmp2 = GetElement(jsobject, index2); Handle<Object> tmp2 = Object::GetElement(jsobject, index2);
RETURN_IF_EMPTY_HANDLE(isolate, tmp2); RETURN_IF_EMPTY_HANDLE(isolate, tmp2);
RETURN_IF_EMPTY_HANDLE(isolate, RETURN_IF_EMPTY_HANDLE(isolate,
@ -11629,7 +11628,7 @@ Object* Runtime::FindSharedFunctionInfoInScript(Isolate* isolate,
if (!done) { if (!done) {
// If the candidate is not compiled compile it to reveal any inner // If the candidate is not compiled compile it to reveal any inner
// functions which might contain the requested source position. // functions which might contain the requested source position.
CompileLazyShared(target, KEEP_EXCEPTION); SharedFunctionInfo::CompileLazy(target, KEEP_EXCEPTION);
} }
} // End while loop. } // End while loop.
@ -12376,7 +12375,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugDisassembleFunction) {
// Get the function and make sure it is compiled. // Get the function and make sure it is compiled.
CONVERT_ARG_CHECKED(JSFunction, func, 0); CONVERT_ARG_CHECKED(JSFunction, func, 0);
Handle<SharedFunctionInfo> shared(func->shared()); Handle<SharedFunctionInfo> shared(func->shared());
if (!EnsureCompiled(shared, KEEP_EXCEPTION)) { if (!SharedFunctionInfo::EnsureCompiled(shared, KEEP_EXCEPTION)) {
return Failure::Exception(); return Failure::Exception();
} }
func->code()->PrintLn(); func->code()->PrintLn();
@ -12392,7 +12391,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugDisassembleConstructor) {
// Get the function and make sure it is compiled. // Get the function and make sure it is compiled.
CONVERT_ARG_CHECKED(JSFunction, func, 0); CONVERT_ARG_CHECKED(JSFunction, func, 0);
Handle<SharedFunctionInfo> shared(func->shared()); Handle<SharedFunctionInfo> shared(func->shared());
if (!EnsureCompiled(shared, KEEP_EXCEPTION)) { if (!SharedFunctionInfo::EnsureCompiled(shared, KEEP_EXCEPTION)) {
return Failure::Exception(); return Failure::Exception();
} }
shared->construct_stub()->PrintLn(); shared->construct_stub()->PrintLn();

View File

@ -626,16 +626,14 @@ class Runtime : public AllStatic {
static bool IsUpperCaseChar(RuntimeState* runtime_state, uint16_t ch); static bool IsUpperCaseChar(RuntimeState* runtime_state, uint16_t ch);
// TODO(1240886): The following three methods are *not* handle safe, // TODO(1240886): Some of the following methods are *not* handle safe, but
// but accept handle arguments. This seems fragile. // accept handle arguments. This seems fragile.
// Support getting the characters in a string using [] notation as // Support getting the characters in a string using [] notation as
// in Firefox/SpiderMonkey, Safari and Opera. // in Firefox/SpiderMonkey, Safari and Opera.
MUST_USE_RESULT static MaybeObject* GetElementOrCharAt(Isolate* isolate, MUST_USE_RESULT static MaybeObject* GetElementOrCharAt(Isolate* isolate,
Handle<Object> object, Handle<Object> object,
uint32_t index); uint32_t index);
MUST_USE_RESULT static MaybeObject* GetElement(Handle<Object> object,
uint32_t index);
MUST_USE_RESULT static MaybeObject* SetObjectProperty( MUST_USE_RESULT static MaybeObject* SetObjectProperty(
Isolate* isolate, Isolate* isolate,

View File

@ -557,6 +557,13 @@ enum VariableMode {
// in a context // in a context
}; };
enum ClearExceptionFlag {
KEEP_EXCEPTION,
CLEAR_EXCEPTION
};
} } // namespace v8::internal } } // namespace v8::internal
#endif // V8_V8GLOBALS_H_ #endif // V8_V8GLOBALS_H_