Fixed bug in JSObject::GetPropertyAttributePostInterceptor where map transitions would count as properties.
Allowed aliased eval invocations by treating them as evals in the global context. This may change in the future. Added support for accessing the last entered context through the API and renamed Context::Current to Context::GetCurrent and Context::GetSecurityContext to Context::GetCurrentSecurityContext. Fixed bug in the debugger that would cause the debugger scripts to be recursively loaded and changed all disabling of interrupts to be block-structured. Made snapshot data read-only to allow it to be more easily shared across multiple users of V8 when linked as a shared library. git-svn-id: http://v8.googlecode.com/svn/trunk@6 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
212ac23f82
commit
44510671e9
20
ChangeLog
20
ChangeLog
@ -1,3 +1,23 @@
|
||||
2008-07-25: Version 0.1.3 (128832)
|
||||
|
||||
Fixed bug in JSObject::GetPropertyAttributePostInterceptor where
|
||||
map transitions would count as properties.
|
||||
|
||||
Allowed aliased eval invocations by treating them as evals in the
|
||||
global context. This may change in the future.
|
||||
|
||||
Added support for accessing the last entered context through the
|
||||
API and renamed Context::Current to Context::GetCurrent and
|
||||
Context::GetSecurityContext to Context::GetCurrentSecurityContext.
|
||||
|
||||
Fixed bug in the debugger that would cause the debugger scripts to
|
||||
be recursively loaded and changed all disabling of interrupts to
|
||||
be block-structured.
|
||||
|
||||
Made snapshot data read-only to allow it to be more easily shared
|
||||
across multiple users of V8 when linked as a shared library.
|
||||
|
||||
|
||||
2008-07-16: Version 0.1.2 (127441)
|
||||
|
||||
Fixed building on Mac OS X by recognizing i386 and friends as
|
||||
|
11
public/v8.h
11
public/v8.h
@ -1779,11 +1779,14 @@ class Context {
|
||||
Handle<ObjectTemplate>(),
|
||||
Handle<Value> global_object = Handle<Value>());
|
||||
|
||||
/** Returns the context that is on the top of the stack.*/
|
||||
static Local<Context> Current();
|
||||
/** Returns the last entered context. */
|
||||
static Local<Context> GetEntered();
|
||||
|
||||
/** Returns the security context used to start JS execution.*/
|
||||
static Local<Context> GetSecurityContext();
|
||||
/** Returns the context that is on the top of the stack. */
|
||||
static Local<Context> GetCurrent();
|
||||
|
||||
/** Returns the security context that is currently used. */
|
||||
static Local<Context> GetCurrentSecurityContext();
|
||||
|
||||
/**
|
||||
* Sets the security token for the context. To access an object in
|
||||
|
34
src/api.cc
34
src/api.cc
@ -403,11 +403,12 @@ void** v8::HandleScope::CreateHandle(void* value) {
|
||||
void Context::Enter() {
|
||||
if (IsDeadCheck("v8::Context::Enter()")) return;
|
||||
i::Handle<i::Context> env = Utils::OpenHandle(this);
|
||||
thread_local.EnterContext(env);
|
||||
|
||||
thread_local.AddEnteredContext(i::GlobalHandles::Create(i::Top::context()));
|
||||
thread_local.SaveContext(i::GlobalHandles::Create(i::Top::context()));
|
||||
i::Top::set_context(*env);
|
||||
|
||||
thread_local.AddSecurityContext(
|
||||
thread_local.SaveSecurityContext(
|
||||
i::GlobalHandles::Create(i::Top::security_context()));
|
||||
i::Top::set_security_context(*env);
|
||||
}
|
||||
@ -415,14 +416,19 @@ void Context::Enter() {
|
||||
|
||||
void Context::Exit() {
|
||||
if (has_shut_down) return;
|
||||
if (!ApiCheck(thread_local.LeaveLastContext(),
|
||||
"v8::Context::Exit()",
|
||||
"Cannot exit non-entered context")) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Content of 'last_context' and 'last_security_context' could be NULL.
|
||||
i::Handle<i::Object> last_context = thread_local.RemoveLastEnteredContext();
|
||||
i::Handle<i::Object> last_context = thread_local.RestoreContext();
|
||||
i::Top::set_context(static_cast<i::Context*>(*last_context));
|
||||
i::GlobalHandles::Destroy(last_context.location());
|
||||
|
||||
i::Handle<i::Object> last_security_context =
|
||||
thread_local.RemoveLastSecurityContext();
|
||||
thread_local.RestoreSecurityContext();
|
||||
i::Top::set_security_context(
|
||||
static_cast<i::Context*>(*last_security_context));
|
||||
i::GlobalHandles::Destroy(last_security_context.location());
|
||||
@ -2145,16 +2151,26 @@ bool Context::InSecurityContext() {
|
||||
}
|
||||
|
||||
|
||||
v8::Local<v8::Context> Context::Current() {
|
||||
if (IsDeadCheck("v8::Context::Current()")) return Local<Context>();
|
||||
v8::Local<v8::Context> Context::GetEntered() {
|
||||
if (IsDeadCheck("v8::Context::GetEntered()")) return Local<Context>();
|
||||
i::Handle<i::Object> last = thread_local.LastEnteredContext();
|
||||
if (last.is_null()) return Local<Context>();
|
||||
i::Handle<i::Context> context = i::Handle<i::Context>::cast(last);
|
||||
return Utils::ToLocal(context);
|
||||
}
|
||||
|
||||
|
||||
v8::Local<v8::Context> Context::GetCurrent() {
|
||||
if (IsDeadCheck("v8::Context::GetCurrent()")) return Local<Context>();
|
||||
i::Handle<i::Context> context(i::Top::global_context());
|
||||
return Utils::ToLocal(context);
|
||||
}
|
||||
|
||||
|
||||
v8::Local<v8::Context> Context::GetSecurityContext() {
|
||||
if (IsDeadCheck("v8::Context::GetSecurityContext()")) return Local<Context>();
|
||||
ASSERT(i::Top::security_context() != NULL);
|
||||
v8::Local<v8::Context> Context::GetCurrentSecurityContext() {
|
||||
if (IsDeadCheck("v8::Context::GetCurrentSecurityContext()")) {
|
||||
return Local<Context>();
|
||||
}
|
||||
i::Handle<i::Context> context(i::Top::security_context());
|
||||
return Utils::ToLocal(context);
|
||||
}
|
||||
|
87
src/api.h
87
src/api.h
@ -345,15 +345,17 @@ class HandleScopeImplementer {
|
||||
|
||||
HandleScopeImplementer()
|
||||
: blocks(0),
|
||||
entered_contexts(0),
|
||||
security_contexts(0) {
|
||||
entered_contexts_(0),
|
||||
saved_contexts_(0),
|
||||
saved_security_contexts_(0) {
|
||||
Initialize();
|
||||
}
|
||||
|
||||
void Initialize() {
|
||||
blocks.Initialize(0);
|
||||
entered_contexts.Initialize(0);
|
||||
security_contexts.Initialize(0);
|
||||
entered_contexts_.Initialize(0);
|
||||
saved_contexts_.Initialize(0);
|
||||
saved_security_contexts_.Initialize(0);
|
||||
spare = NULL;
|
||||
ignore_out_of_memory = false;
|
||||
call_depth = 0;
|
||||
@ -378,12 +380,20 @@ class HandleScopeImplementer {
|
||||
inline void DecrementCallDepth() {call_depth--;}
|
||||
inline bool CallDepthIsZero() { return call_depth == 0; }
|
||||
|
||||
inline void AddEnteredContext(Handle<Object>);
|
||||
inline Handle<Object> RemoveLastEnteredContext();
|
||||
inline bool HasEnteredContexts();
|
||||
inline void AddSecurityContext(Handle<Object>);
|
||||
inline Handle<Object> RemoveLastSecurityContext();
|
||||
inline bool HasSecurityContexts();
|
||||
inline void EnterContext(Handle<Object> context);
|
||||
inline bool LeaveLastContext();
|
||||
|
||||
// Returns the last entered context or an empty handle if no
|
||||
// contexts have been entered.
|
||||
inline Handle<Object> LastEnteredContext();
|
||||
|
||||
inline void SaveContext(Handle<Object> context);
|
||||
inline Handle<Object> RestoreContext();
|
||||
inline bool HasSavedContexts();
|
||||
|
||||
inline void SaveSecurityContext(Handle<Object> context);
|
||||
inline Handle<Object> RestoreSecurityContext();
|
||||
inline bool HasSavedSecurityContexts();
|
||||
|
||||
inline List<void**>* Blocks() { return &blocks; }
|
||||
|
||||
@ -394,10 +404,12 @@ class HandleScopeImplementer {
|
||||
List<void**> blocks;
|
||||
Object** spare;
|
||||
int call_depth;
|
||||
// Used as a stack to keep track of contexts entered.
|
||||
List<Handle<Object> > entered_contexts;
|
||||
// Used as a stack to keep track of security contexts entered.
|
||||
List<Handle<Object> > security_contexts;
|
||||
// Used as a stack to keep track of entered contexts.
|
||||
List<Handle<Object> > entered_contexts_;
|
||||
// Used as a stack to keep track of saved contexts.
|
||||
List<Handle<Object> > saved_contexts_;
|
||||
// Used as a stack to keep track of saved security contexts.
|
||||
List<Handle<Object> > saved_security_contexts_;
|
||||
bool ignore_out_of_memory;
|
||||
// This is only used for threading support.
|
||||
ImplementationUtilities::HandleScopeData handle_scope_data_;
|
||||
@ -415,32 +427,51 @@ class HandleScopeImplementer {
|
||||
static const int kHandleBlockSize = v8::internal::KB - 2; // fit in one page
|
||||
|
||||
|
||||
void HandleScopeImplementer::AddEnteredContext(Handle<Object> context) {
|
||||
entered_contexts.Add(context);
|
||||
void HandleScopeImplementer::SaveContext(Handle<Object> context) {
|
||||
saved_contexts_.Add(context);
|
||||
}
|
||||
|
||||
|
||||
Handle<Object> HandleScopeImplementer::RemoveLastEnteredContext() {
|
||||
return entered_contexts.RemoveLast();
|
||||
Handle<Object> HandleScopeImplementer::RestoreContext() {
|
||||
return saved_contexts_.RemoveLast();
|
||||
}
|
||||
|
||||
|
||||
bool HandleScopeImplementer::HasEnteredContexts() {
|
||||
return !entered_contexts.is_empty();
|
||||
}
|
||||
|
||||
void HandleScopeImplementer::AddSecurityContext(Handle<Object> context) {
|
||||
security_contexts.Add(context);
|
||||
bool HandleScopeImplementer::HasSavedContexts() {
|
||||
return !saved_contexts_.is_empty();
|
||||
}
|
||||
|
||||
|
||||
Handle<Object> HandleScopeImplementer::RemoveLastSecurityContext() {
|
||||
return security_contexts.RemoveLast();
|
||||
void HandleScopeImplementer::SaveSecurityContext(Handle<Object> context) {
|
||||
saved_security_contexts_.Add(context);
|
||||
}
|
||||
|
||||
|
||||
bool HandleScopeImplementer::HasSecurityContexts() {
|
||||
return !security_contexts.is_empty();
|
||||
Handle<Object> HandleScopeImplementer::RestoreSecurityContext() {
|
||||
return saved_security_contexts_.RemoveLast();
|
||||
}
|
||||
|
||||
|
||||
bool HandleScopeImplementer::HasSavedSecurityContexts() {
|
||||
return !saved_security_contexts_.is_empty();
|
||||
}
|
||||
|
||||
|
||||
void HandleScopeImplementer::EnterContext(Handle<Object> context) {
|
||||
entered_contexts_.Add(context);
|
||||
}
|
||||
|
||||
|
||||
bool HandleScopeImplementer::LeaveLastContext() {
|
||||
if (entered_contexts_.is_empty()) return false;
|
||||
entered_contexts_.RemoveLast();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Handle<Object> HandleScopeImplementer::LastEnteredContext() {
|
||||
if (entered_contexts_.is_empty()) return Handle<Object>::null();
|
||||
return entered_contexts_.last();
|
||||
}
|
||||
|
||||
|
||||
|
@ -83,7 +83,6 @@ void VariableProxy::BindTo(Variable* var) {
|
||||
// non-const) multiple variable declarations, const vars introduced via
|
||||
// eval() etc. Const-ness and variable declarations are a complete mess
|
||||
// in JS. Sigh...
|
||||
// ASSERT(var->mode() == Variable::CONST || !is_const());
|
||||
var_ = var;
|
||||
var->var_uses()->RecordUses(&var_uses_);
|
||||
var->obj_uses()->RecordUses(&obj_uses_);
|
||||
|
@ -112,7 +112,7 @@ static Handle<JSFunction> MakeFunction(bool is_global,
|
||||
|
||||
// Make sure we have an initial stack limit.
|
||||
StackGuard guard;
|
||||
StackGuard::DisableInterrupts();
|
||||
PostponeInterruptsScope postpone;
|
||||
|
||||
// Notify debugger
|
||||
Debugger::OnBeforeCompile(script);
|
||||
@ -126,7 +126,6 @@ static Handle<JSFunction> MakeFunction(bool is_global,
|
||||
// Check for parse errors.
|
||||
if (lit == NULL) {
|
||||
ASSERT(Top::has_pending_exception());
|
||||
StackGuard::EnableInterrupts();
|
||||
return Handle<JSFunction>::null();
|
||||
}
|
||||
|
||||
@ -144,7 +143,6 @@ static Handle<JSFunction> MakeFunction(bool is_global,
|
||||
// Check for stack-overflow exceptions.
|
||||
if (code.is_null()) {
|
||||
Top::StackOverflow();
|
||||
StackGuard::EnableInterrupts();
|
||||
return Handle<JSFunction>::null();
|
||||
}
|
||||
|
||||
@ -172,8 +170,6 @@ static Handle<JSFunction> MakeFunction(bool is_global,
|
||||
// the instances of the function.
|
||||
SetExpectedNofPropertiesFromEstimate(fun, lit->expected_property_count());
|
||||
|
||||
StackGuard::EnableInterrupts();
|
||||
|
||||
// Notify debugger
|
||||
Debugger::OnAfterCompile(script, fun);
|
||||
|
||||
@ -242,7 +238,7 @@ bool Compiler::CompileLazy(Handle<SharedFunctionInfo> shared) {
|
||||
|
||||
// Make sure we have an initial stack limit.
|
||||
StackGuard guard;
|
||||
StackGuard::DisableInterrupts();
|
||||
PostponeInterruptsScope postpone;
|
||||
|
||||
// Compute name, source code and script data.
|
||||
Handle<String> name(String::cast(shared->name()));
|
||||
@ -263,7 +259,6 @@ bool Compiler::CompileLazy(Handle<SharedFunctionInfo> shared) {
|
||||
// Check for parse errors.
|
||||
if (lit == NULL) {
|
||||
ASSERT(Top::has_pending_exception());
|
||||
StackGuard::EnableInterrupts();
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -278,7 +273,6 @@ bool Compiler::CompileLazy(Handle<SharedFunctionInfo> shared) {
|
||||
// Check for stack-overflow exception.
|
||||
if (code.is_null()) {
|
||||
Top::StackOverflow();
|
||||
StackGuard::EnableInterrupts();
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -293,7 +287,6 @@ bool Compiler::CompileLazy(Handle<SharedFunctionInfo> shared) {
|
||||
|
||||
// Check the function has compiled code.
|
||||
ASSERT(shared->is_compiled());
|
||||
StackGuard::EnableInterrupts();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
97
src/debug.cc
97
src/debug.cc
@ -530,10 +530,12 @@ void Debug::Setup(bool create_heap_objects) {
|
||||
bool Debug::CompileDebuggerScript(int index) {
|
||||
HandleScope scope;
|
||||
|
||||
// Find source and name for the requested script.
|
||||
// Bail out if the index is invalid.
|
||||
if (index == -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Find source and name for the requested script.
|
||||
Handle<String> source_code = Bootstrapper::NativesSourceLookup(index);
|
||||
Vector<const char> name = Natives::GetScriptName(index);
|
||||
Handle<String> script_name = Factory::NewStringFromAscii(name);
|
||||
@ -552,26 +554,25 @@ bool Debug::CompileDebuggerScript(int index) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Execute the boilerplate function in the global object for the supplied
|
||||
// context.
|
||||
bool caught_exception = false;
|
||||
// Execute the boilerplate function in the debugger context.
|
||||
Handle<Context> context = Top::global_context();
|
||||
Handle<JSFunction> debug_fun(Factory::NewFunctionFromBoilerplate(boilerplate,
|
||||
context));
|
||||
Handle<GlobalObject> debug_global(context->global());
|
||||
Handle<Object> result = Execution::TryCall(debug_fun, debug_global,
|
||||
0, NULL, &caught_exception);
|
||||
bool caught_exception = false;
|
||||
Handle<JSFunction> function =
|
||||
Factory::NewFunctionFromBoilerplate(boilerplate, context);
|
||||
Handle<Object> result =
|
||||
Execution::TryCall(function, Handle<Object>(context->global()),
|
||||
0, NULL, &caught_exception);
|
||||
|
||||
// Check for caught exceptions.
|
||||
if (caught_exception) {
|
||||
MessageHandler::ReportMessage("error_loading_debugger",
|
||||
NULL,
|
||||
MessageHandler::ReportMessage("error_loading_debugger", NULL,
|
||||
HandleVector<Object>(&result, 1));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Mark this script as native.
|
||||
Handle<Script> script(Script::cast(debug_fun->shared()->script()));
|
||||
// Mark this script as native and return successfully.
|
||||
Handle<Script> script(Script::cast(function->shared()->script()));
|
||||
script->set_type(Smi::FromInt(SCRIPT_TYPE_NATIVE));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -580,39 +581,44 @@ bool Debug::Load() {
|
||||
// Return if debugger is already loaded.
|
||||
if (IsLoaded()) return true;
|
||||
|
||||
// Bail out if we're already in the process of compiling the native
|
||||
// JavaScript source code for the debugger.
|
||||
if (Debugger::compiling_natives()) return false;
|
||||
|
||||
// Disable breakpoints and interrupts while compiling and running the
|
||||
// debugger scripts including the context creation code.
|
||||
DisableBreak disable(true);
|
||||
PostponeInterruptsScope postpone;
|
||||
|
||||
// Create the debugger context.
|
||||
HandleScope scope;
|
||||
Handle<Object> empty_global_object;
|
||||
Handle<Context> debug_context;
|
||||
v8::Handle<v8::ObjectTemplate> global_template =
|
||||
v8::Handle<v8::ObjectTemplate>();
|
||||
debug_context = Bootstrapper::CreateEnvironment(empty_global_object,
|
||||
global_template,
|
||||
NULL);
|
||||
Handle<Context> context =
|
||||
Bootstrapper::CreateEnvironment(Handle<Object>::null(),
|
||||
v8::Handle<ObjectTemplate>(),
|
||||
NULL);
|
||||
|
||||
// Enter the debugger context.
|
||||
// Use the debugger context.
|
||||
SaveContext save;
|
||||
Top::set_context(*debug_context);
|
||||
Top::set_security_context(*debug_context);
|
||||
Top::set_context(*context);
|
||||
Top::set_security_context(*context);
|
||||
|
||||
// Expose the builtins object in the debugger context.
|
||||
Handle<String> key = Factory::LookupAsciiSymbol("builtins");
|
||||
Handle<GlobalObject> global = Handle<GlobalObject>(context->global());
|
||||
SetProperty(global, key, Handle<Object>(global->builtins()), NONE);
|
||||
|
||||
// Compile the JavaScript for the debugger in the debugger context.
|
||||
Debugger::set_compiling_natives(true);
|
||||
if (!CompileDebuggerScript(Natives::GetIndex("mirror"))) {
|
||||
return false;
|
||||
};
|
||||
if (!CompileDebuggerScript(Natives::GetIndex("debug"))) {
|
||||
return false;
|
||||
};
|
||||
bool caught_exception =
|
||||
!CompileDebuggerScript(Natives::GetIndex("mirror")) ||
|
||||
!CompileDebuggerScript(Natives::GetIndex("debug"));
|
||||
Debugger::set_compiling_natives(false);
|
||||
|
||||
// Expose the builtins object in the debugger context.
|
||||
Handle<String> builtins_string = Factory::LookupAsciiSymbol("builtins");
|
||||
Handle<JSGlobalObject> global(JSGlobalObject::cast(debug_context->global()));
|
||||
SetProperty(global, builtins_string,
|
||||
Handle<JSObject>(global->builtins()), NONE);
|
||||
// Check for caught exceptions.
|
||||
if (caught_exception) return false;
|
||||
|
||||
// Debugger loaded.
|
||||
debug_context_ = Handle<Context>::cast(GlobalHandles::Create(*debug_context));
|
||||
debug_context_ = Handle<Context>::cast(GlobalHandles::Create(*context));
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -654,8 +660,8 @@ Object* Debug::Break(Arguments args) {
|
||||
SaveBreakFrame save;
|
||||
EnterDebuggerContext enter;
|
||||
|
||||
// Deactivate interrupt during breakpoint processing.
|
||||
StackGuard::DisableInterrupts();
|
||||
// Postpone interrupt during breakpoint processing.
|
||||
PostponeInterruptsScope postpone;
|
||||
|
||||
// Get the debug info (create it if it does not exist).
|
||||
Handle<SharedFunctionInfo> shared =
|
||||
@ -707,9 +713,6 @@ Object* Debug::Break(Arguments args) {
|
||||
PrepareStep(step_action, step_count);
|
||||
}
|
||||
|
||||
// Reactivate interrupt.
|
||||
StackGuard::EnableInterrupts();
|
||||
|
||||
// Install jump to the call address which was overwritten.
|
||||
SetAfterBreakTarget(frame);
|
||||
|
||||
@ -1344,8 +1347,8 @@ void Debugger::DebugRequest(const uint16_t* json_request, int length) {
|
||||
pending_requests_tail_ = pending_request;
|
||||
}
|
||||
|
||||
// Use the stack guard to signal the debug request.
|
||||
StackGuard::DebugBreak();
|
||||
// Set the pending request flag to force the VM to stop soon.
|
||||
v8::Debug::DebugBreak();
|
||||
}
|
||||
|
||||
|
||||
@ -1517,7 +1520,7 @@ Handle<String> Debugger::ProcessRequest(Handle<Object> exec_state,
|
||||
|
||||
bool Debugger::IsPlainBreakRequest(Handle<Object> request) {
|
||||
// Get the function IsPlainBreakRequest (defined in debug.js).
|
||||
Handle<JSFunction> process_denbug_request =
|
||||
Handle<JSFunction> process_debug_request =
|
||||
Handle<JSFunction>(JSFunction::cast(
|
||||
Debug::debug_context()->global()->GetProperty(
|
||||
*Factory::LookupAsciiSymbol("IsPlainBreakRequest"))));
|
||||
@ -1526,7 +1529,7 @@ bool Debugger::IsPlainBreakRequest(Handle<Object> request) {
|
||||
bool caught_exception;
|
||||
const int argc = 1;
|
||||
Object** argv[argc] = { request.location() };
|
||||
Handle<Object> result = Execution::TryCall(process_denbug_request,
|
||||
Handle<Object> result = Execution::TryCall(process_debug_request,
|
||||
Factory::undefined_value(),
|
||||
argc, argv,
|
||||
&caught_exception);
|
||||
@ -1962,8 +1965,8 @@ void DebugMessageThread::Run() {
|
||||
}
|
||||
|
||||
|
||||
// This method is called by the V8 thread whenever a debug event occours in the
|
||||
// vm.
|
||||
// This method is called by the V8 thread whenever a debug event occurs in
|
||||
// the VM.
|
||||
void DebugMessageThread::DebugEvent(v8::DebugEvent event,
|
||||
Handle<Object> exec_state,
|
||||
Handle<Object> event_data) {
|
||||
|
@ -75,7 +75,8 @@ static Handle<Object> Invoke(bool construct,
|
||||
code = stub.GetCode();
|
||||
}
|
||||
|
||||
{ // Save and restore context around invocation and block the
|
||||
{
|
||||
// Save and restore context around invocation and block the
|
||||
// allocation of handles without explicit handle scopes.
|
||||
SaveContext save;
|
||||
NoHandleAllocation na;
|
||||
@ -296,6 +297,7 @@ bool StackGuard::IsDebugBreak() {
|
||||
return thread_local_.interrupt_flags_ & DEBUGBREAK;
|
||||
}
|
||||
|
||||
|
||||
void StackGuard::DebugBreak() {
|
||||
ExecutionAccess access;
|
||||
if (!Top::is_break_no_lock()) {
|
||||
|
@ -147,8 +147,6 @@ class StackGuard BASE_EMBEDDED {
|
||||
static int ArchiveSpacePerThread();
|
||||
|
||||
static bool IsStackOverflow();
|
||||
static void EnableInterrupts();
|
||||
static void DisableInterrupts();
|
||||
static bool IsPreempted();
|
||||
static void Preempt();
|
||||
static bool IsInterrupted();
|
||||
@ -186,6 +184,10 @@ class StackGuard BASE_EMBEDDED {
|
||||
}
|
||||
}
|
||||
|
||||
// Enable or disable interrupts.
|
||||
static void EnableInterrupts();
|
||||
static void DisableInterrupts();
|
||||
|
||||
static const int kLimitSize = 512 * KB;
|
||||
static const uintptr_t kInterruptLimit = 0xfffffffe;
|
||||
static const uintptr_t kIllegalLimit = 0xffffffff;
|
||||
@ -198,16 +200,21 @@ class StackGuard BASE_EMBEDDED {
|
||||
initial_climit_(kIllegalLimit),
|
||||
climit_(kIllegalLimit),
|
||||
nesting_(0),
|
||||
postpone_interrupts_nesting_(0),
|
||||
interrupt_flags_(0) {}
|
||||
uintptr_t initial_jslimit_;
|
||||
uintptr_t jslimit_;
|
||||
uintptr_t initial_climit_;
|
||||
uintptr_t climit_;
|
||||
int nesting_;
|
||||
int postpone_interrupts_nesting_;
|
||||
int interrupt_flags_;
|
||||
};
|
||||
|
||||
static ThreadLocal thread_local_;
|
||||
|
||||
friend class StackLimitCheck;
|
||||
friend class PostponeInterruptsScope;
|
||||
};
|
||||
|
||||
|
||||
@ -220,6 +227,25 @@ class StackLimitCheck BASE_EMBEDDED {
|
||||
};
|
||||
|
||||
|
||||
// Support for temporarily postponing interrupts. When the outermost
|
||||
// postpone scope is left the interrupts will be re-enabled and any
|
||||
// interrupts that occured while in the scope will be taken into
|
||||
// account.
|
||||
class PostponeInterruptsScope BASE_EMBEDDED {
|
||||
public:
|
||||
PostponeInterruptsScope() {
|
||||
StackGuard::thread_local_.postpone_interrupts_nesting_++;
|
||||
StackGuard::DisableInterrupts();
|
||||
}
|
||||
|
||||
~PostponeInterruptsScope() {
|
||||
if (--StackGuard::thread_local_.postpone_interrupts_nesting_ == 0) {
|
||||
StackGuard::EnableInterrupts();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class PrintExtension : public v8::Extension {
|
||||
public:
|
||||
PrintExtension() : v8::Extension("v8/print", kSource) { }
|
||||
|
@ -132,7 +132,7 @@ static int WriteInternalSnapshotToFile(const char* filename,
|
||||
fprintf(f, "#include \"platform.h\"\n\n");
|
||||
fprintf(f, "#include \"snapshot.h\"\n\n");
|
||||
fprintf(f, "namespace v8 {\nnamespace internal {\n\n");
|
||||
fprintf(f, "char Snapshot::data_[] = {");
|
||||
fprintf(f, "const char Snapshot::data_[] = {");
|
||||
int written = 0;
|
||||
written += fprintf(f, "%i", str[0]);
|
||||
for (int i = 1; i < size; ++i) {
|
||||
|
@ -348,7 +348,7 @@ Object* Object::GetProperty(Object* receiver,
|
||||
if (current == last) break;
|
||||
}
|
||||
|
||||
if (!result->IsValid()) {
|
||||
if (!result->IsProperty()) {
|
||||
*attributes = ABSENT;
|
||||
return Heap::undefined_value();
|
||||
}
|
||||
@ -378,17 +378,14 @@ Object* Object::GetProperty(Object* receiver,
|
||||
result->GetCallbackObject(),
|
||||
name,
|
||||
holder);
|
||||
case MAP_TRANSITION:
|
||||
case CONSTANT_TRANSITION:
|
||||
*attributes = ABSENT;
|
||||
return Heap::undefined_value();
|
||||
case INTERCEPTOR: {
|
||||
JSObject* recvr = JSObject::cast(receiver);
|
||||
return holder->GetPropertyWithInterceptor(recvr, name, attributes);
|
||||
}
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return NULL;
|
||||
}
|
||||
UNREACHABLE();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@ -1571,7 +1568,7 @@ PropertyAttributes JSObject::GetPropertyAttributePostInterceptor(
|
||||
// Check local property, ignore interceptor.
|
||||
LookupResult result;
|
||||
LocalLookupRealNamedProperty(name, &result);
|
||||
if (result.IsValid()) return result.GetAttributes();
|
||||
if (result.IsProperty()) return result.GetAttributes();
|
||||
|
||||
if (continue_search) {
|
||||
// Continue searching via the prototype chain.
|
||||
|
@ -2988,8 +2988,8 @@ static Object* RuntimePreempt(Arguments args) {
|
||||
|
||||
|
||||
static Object* Runtime_DebugBreak(Arguments args) {
|
||||
// Just continue if breaks are disabled.
|
||||
if (Debug::disable_break()) {
|
||||
// Just continue if breaks are disabled or if we fail to load the debugger.
|
||||
if (Debug::disable_break() || !Debug::Load()) {
|
||||
return args[0];
|
||||
}
|
||||
|
||||
@ -3009,11 +3009,6 @@ static Object* Runtime_DebugBreak(Arguments args) {
|
||||
// Clear the debug request flag.
|
||||
StackGuard::Continue(DEBUGBREAK);
|
||||
|
||||
// Make sure debugger is loaded.
|
||||
if (!Debug::Load()) {
|
||||
return args[0];
|
||||
}
|
||||
|
||||
HandleScope scope;
|
||||
SaveBreakFrame save;
|
||||
EnterDebuggerContext enter;
|
||||
@ -3309,13 +3304,15 @@ static Object* EvalContext() {
|
||||
StackFrameLocator locator;
|
||||
JavaScriptFrame* frame = locator.FindJavaScriptFrame(1);
|
||||
|
||||
// Check if the caller of eval() supports eval. If not, eval is
|
||||
// called through an alias in which case we throw an EvalError.
|
||||
// TODO(900055): Right now we check if the caller of eval() supports
|
||||
// eval to determine if it's an aliased eval or not. This may not be
|
||||
// entirely correct in the unlikely case where a function uses both
|
||||
// aliased and direct eval calls.
|
||||
HandleScope scope;
|
||||
if (!ScopeInfo<>::SupportsEval(frame->FindCode())) {
|
||||
Handle<Object> error =
|
||||
Factory::NewEvalError("illegal_eval", HandleVector<Object>(NULL, 0));
|
||||
return Top::Throw(*error);
|
||||
// Aliased eval: Evaluate in the global context of the eval
|
||||
// function to support aliased, cross environment evals.
|
||||
return *Top::global_context();
|
||||
}
|
||||
|
||||
// Fetch the caller context from the frame.
|
||||
@ -4885,6 +4882,9 @@ static Object* Runtime_Abort(Arguments args) {
|
||||
}
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
// ListNatives is ONLY used by the fuzz-natives.js in debug mode
|
||||
// Exclude the code in release mode.
|
||||
static Object* Runtime_ListNatives(Arguments args) {
|
||||
ASSERT(args.length() == 1);
|
||||
HandleScope scope;
|
||||
@ -4904,6 +4904,7 @@ static Object* Runtime_ListNatives(Arguments args) {
|
||||
#undef ADD_ENTRY
|
||||
return *result;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static Object* Runtime_IS_VAR(Arguments args) {
|
||||
|
@ -33,11 +33,11 @@ namespace v8 { namespace internal {
|
||||
// The interface to C++ runtime functions.
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// RUNTIME_FUNCTION_LIST defines all runtime functions accessed
|
||||
// either directly by id (via the code generator), or indirectly
|
||||
// via a native call by name (from within JS code).
|
||||
// RUNTIME_FUNCTION_LIST_ALWAYS defines runtime calls available in both
|
||||
// release and debug mode.
|
||||
// This macro should only be used by the macro RUNTIME_FUNCTION_LIST.
|
||||
|
||||
#define RUNTIME_FUNCTION_LIST(F) \
|
||||
#define RUNTIME_FUNCTION_LIST_ALWAYS(F) \
|
||||
/* Property access */ \
|
||||
F(AddProperty, 4) \
|
||||
F(GetProperty, 2) \
|
||||
@ -279,13 +279,28 @@ namespace v8 { namespace internal {
|
||||
F(FunctionGetAssemblerCode, 1) \
|
||||
F(Abort, 2) \
|
||||
\
|
||||
/* Testing */ \
|
||||
F(ListNatives, 1) \
|
||||
\
|
||||
/* Pseudo functions - handled as macros by parser */ \
|
||||
F(IS_VAR, 1)
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
#define RUNTIME_FUNCTION_LIST_DEBUG(F) \
|
||||
/* Testing */ \
|
||||
F(ListNatives, 1)
|
||||
#else
|
||||
#define RUNTIME_FUNCTION_LIST_DEBUG(F)
|
||||
#endif
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// RUNTIME_FUNCTION_LIST defines all runtime functions accessed
|
||||
// either directly by id (via the code generator), or indirectly
|
||||
// via a native call by name (from within JS code).
|
||||
|
||||
#define RUNTIME_FUNCTION_LIST(F) \
|
||||
RUNTIME_FUNCTION_LIST_ALWAYS(F) \
|
||||
RUNTIME_FUNCTION_LIST_DEBUG(F)
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Runtime provides access to all C++ runtime functions.
|
||||
|
||||
|
@ -921,17 +921,18 @@ void Serializer::PutGlobalHandleStack(const List<Handle<Object> >& stack) {
|
||||
|
||||
|
||||
void Serializer::PutContextStack() {
|
||||
List<Handle<Object> > entered_contexts(2);
|
||||
while (HandleScopeImplementer::instance()->HasEnteredContexts()) {
|
||||
List<Handle<Object> > contexts(2);
|
||||
while (HandleScopeImplementer::instance()->HasSavedContexts()) {
|
||||
Handle<Object> context =
|
||||
HandleScopeImplementer::instance()->RemoveLastEnteredContext();
|
||||
entered_contexts.Add(context);
|
||||
HandleScopeImplementer::instance()->RestoreContext();
|
||||
contexts.Add(context);
|
||||
}
|
||||
PutGlobalHandleStack(entered_contexts);
|
||||
PutGlobalHandleStack(contexts);
|
||||
|
||||
List<Handle<Object> > security_contexts(2);
|
||||
while (HandleScopeImplementer::instance()->HasSecurityContexts()) {
|
||||
while (HandleScopeImplementer::instance()->HasSavedSecurityContexts()) {
|
||||
Handle<Object> context =
|
||||
HandleScopeImplementer::instance()->RemoveLastSecurityContext();
|
||||
HandleScopeImplementer::instance()->RestoreSecurityContext();
|
||||
security_contexts.Add(context);
|
||||
}
|
||||
PutGlobalHandleStack(security_contexts);
|
||||
@ -1049,7 +1050,7 @@ RelativeAddress Serializer::Allocate(HeapObject* obj) {
|
||||
static const int kInitArraySize = 32;
|
||||
|
||||
|
||||
Deserializer::Deserializer(char* str, int len)
|
||||
Deserializer::Deserializer(const char* str, int len)
|
||||
: reader_(str, len),
|
||||
map_pages_(kInitArraySize), old_pages_(kInitArraySize),
|
||||
code_pages_(kInitArraySize), large_objects_(kInitArraySize),
|
||||
@ -1254,13 +1255,13 @@ void Deserializer::GetContextStack() {
|
||||
List<Handle<Object> > entered_contexts(2);
|
||||
GetGlobalHandleStack(&entered_contexts);
|
||||
for (int i = 0; i < entered_contexts.length(); i++) {
|
||||
HandleScopeImplementer::instance()->AddEnteredContext(entered_contexts[i]);
|
||||
HandleScopeImplementer::instance()->SaveContext(entered_contexts[i]);
|
||||
}
|
||||
List<Handle<Object> > security_contexts(2);
|
||||
GetGlobalHandleStack(&security_contexts);
|
||||
for (int i = 0; i < security_contexts.length(); i++) {
|
||||
HandleScopeImplementer::instance()->
|
||||
AddSecurityContext(security_contexts[i]);
|
||||
SaveSecurityContext(security_contexts[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -202,7 +202,7 @@ class Serializer: public ObjectVisitor {
|
||||
|
||||
class SnapshotReader {
|
||||
public:
|
||||
SnapshotReader(char* str, int len): str_(str), end_(str + len) {}
|
||||
SnapshotReader(const char* str, int len): str_(str), end_(str + len) {}
|
||||
|
||||
void ExpectC(char expected) {
|
||||
int c = GetC();
|
||||
@ -216,7 +216,7 @@ class SnapshotReader {
|
||||
}
|
||||
|
||||
int GetInt() {
|
||||
int result = *reinterpret_cast<int*>(str_);
|
||||
int result = *reinterpret_cast<const int*>(str_);
|
||||
str_ += sizeof(result);
|
||||
return result;
|
||||
}
|
||||
@ -238,8 +238,8 @@ class SnapshotReader {
|
||||
}
|
||||
|
||||
private:
|
||||
char* str_;
|
||||
char* end_;
|
||||
const char* str_;
|
||||
const char* end_;
|
||||
};
|
||||
|
||||
|
||||
@ -249,7 +249,7 @@ class Deserializer: public ObjectVisitor {
|
||||
public:
|
||||
// Create a deserializer. The snapshot is held in str and has size len.
|
||||
// Ownership of str is not assumed by the Deserializer.
|
||||
Deserializer(char* str, int len);
|
||||
Deserializer(const char* str, int len);
|
||||
|
||||
virtual ~Deserializer();
|
||||
|
||||
|
@ -35,7 +35,7 @@
|
||||
|
||||
namespace v8 { namespace internal {
|
||||
|
||||
bool Snapshot::Deserialize(char* content, int len) {
|
||||
bool Snapshot::Deserialize(const char* content, int len) {
|
||||
Deserializer des(content, len);
|
||||
des.GetFlags();
|
||||
return V8::Initialize(&des);
|
||||
|
@ -33,7 +33,7 @@
|
||||
|
||||
namespace v8 { namespace internal {
|
||||
|
||||
char Snapshot::data_[] = { 0 };
|
||||
const char Snapshot::data_[] = { 0 };
|
||||
int Snapshot::size_ = 0;
|
||||
|
||||
} } // namespace v8::internal
|
||||
|
@ -45,10 +45,10 @@ class Snapshot {
|
||||
static bool WriteToFile(const char* snapshot_file);
|
||||
|
||||
private:
|
||||
static char data_[];
|
||||
static const char data_[];
|
||||
static int size_;
|
||||
|
||||
static bool Deserialize(char* content, int len);
|
||||
static bool Deserialize(const char* content, int len);
|
||||
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(Snapshot);
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user