Commit 212ac23f authored by kasper.lund's avatar kasper.lund

Fixed building on Mac OS X by recognizing i386 and friends as IA-32 platforms.

Added propagation of stack overflow exceptions that occur while compiling nested functions.

Improved debugger with support for recursive break points and handling of exceptions that occur in the debugger JavaScript code.

Renamed GetInternal to GetInternalField and SetInternal to SetInternalField in the API and moved InternalFieldCount and SetInternalFieldCount from FunctionTemplate to ObjectTemplate.


git-svn-id: http://v8.googlecode.com/svn/trunk@5 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent bd3ec4e5
2008-07-16: Version 0.1.2 (127441)
Fixed building on Mac OS X by recognizing i386 and friends as
IA-32 platforms.
Added propagation of stack overflow exceptions that occur while
compiling nested functions.
Improved debugger with support for recursive break points and
handling of exceptions that occur in the debugger JavaScript code.
Renamed GetInternal to GetInternalField and SetInternal to
SetInternalField in the API and moved InternalFieldCount and
SetInternalFieldCount from FunctionTemplate to ObjectTemplate.
2008-07-09: Version 0.1.1 (126448)
Fixed bug in stack overflow check code for IA-32 targets where a
......
......@@ -26,6 +26,7 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import platform
import re
import sys
from os.path import join, dirname, abspath
root_dir = dirname(File('SConstruct').rfile().abspath)
......@@ -47,17 +48,17 @@ def GuessOS():
elif id == 'Windows':
return 'win32'
else:
Abort("Don't know how to build v8 for OS '%s'." % id)
return '<none>'
def GuessProcessor():
id = platform.machine()
if id.startswith('arm'):
return 'arm'
elif (not id) or id.startswith('x86'):
elif (not id) or (not re.match('(x|i[3-6])86', id) is None):
return 'ia32'
else:
Abort("Don't know how to build v8 for processor '%s'." % id)
return '<none>'
def GuessToolchain(os):
......@@ -70,8 +71,7 @@ def GuessToolchain(os):
elif 'msvc' in tools:
return 'msvc'
else:
tools = ', '.join(tools)
Abort("Don't know how to build v8 using these tools: %s" % tools)
return '<none>'
def GetOptions():
......
......@@ -905,10 +905,12 @@ class Object : public Value {
*/
Local<String> ObjectProtoToString();
// TODO(1245384): Naming, consistent.
/** Gets the number of internal fields for this Object. */
int InternalFieldCount();
Local<Value> GetInternal(int index);
void SetInternal(int index, Handle<Value> value);
/** Gets the value in an internal field. */
Local<Value> GetInternalField(int index);
/** Sets the value in an internal field. */
void SetInternalField(int index, Handle<Value> value);
// Testers for local properties.
bool HasRealNamedProperty(Handle<String> key);
......@@ -1282,11 +1284,6 @@ class FunctionTemplate : public Template {
*/
Local<ObjectTemplate> PrototypeTemplate();
int InternalFieldCount();
/** Sets the number of internal fields on the object template.*/
void SetInternalFieldCount(int value);
void SetClassName(Handle<String> name);
/**
......@@ -1406,6 +1403,18 @@ class ObjectTemplate : public Template {
IndexedSecurityCallback indexed_handler,
Handle<Value> data = Handle<Value>());
/**
* Gets the number of internal fields for objects generated from
* this template.
*/
int InternalFieldCount();
/**
* Sets the number of internal fields for objects generated from
* this template.
*/
void SetInternalFieldCount(int value);
private:
ObjectTemplate();
static Local<ObjectTemplate> New(Handle<FunctionTemplate> constructor);
......
This diff is collapsed.
......@@ -1217,6 +1217,12 @@ class Visitor BASE_EMBEDDED {
return (stack_overflow_ = true);
}
// If a stack-overflow exception is encountered when visiting a
// node, calling SetStackOverflow will make sure that the visitor
// bails out without visiting more nodes.
void SetStackOverflow() { stack_overflow_ = true; }
// Individual nodes
#define DEF_VISIT(type) \
virtual void Visit##type(type* node) = 0;
......
......@@ -346,7 +346,7 @@ Handle<Code> ArmCodeGenerator::MakeCode(FunctionLiteral* flit,
ArmCodeGenerator cgen(initial_buffer_size, script, is_eval);
cgen.GenCode(flit);
if (cgen.HasStackOverflow()) {
Top::StackOverflow();
ASSERT(!Top::has_pending_exception());
return Handle<Code>::null();
}
......@@ -546,6 +546,9 @@ void ArmCodeGenerator::GenCode(FunctionLiteral* fun) {
} else {
Comment cmnt(masm_, "[ declarations");
ProcessDeclarations(scope->declarations());
// Bail out if a stack-overflow exception occured when
// processing declarations.
if (HasStackOverflow()) return;
}
if (FLAG_trace) __ CallRuntime(Runtime::kTraceEnter, 1);
......@@ -2903,6 +2906,8 @@ void ArmCodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) {
// Build the function boilerplate and instantiate it.
Handle<JSFunction> boilerplate = BuildBoilerplate(node);
// Check for stack-overflow exception.
if (HasStackOverflow()) return;
InstantiateBoilerplate(boilerplate);
}
......
......@@ -361,7 +361,7 @@ Handle<Code> Ia32CodeGenerator::MakeCode(FunctionLiteral* flit,
Ia32CodeGenerator cgen(initial_buffer_size, script, is_eval);
cgen.GenCode(flit);
if (cgen.HasStackOverflow()) {
Top::StackOverflow();
ASSERT(!Top::has_pending_exception());
return Handle<Code>::null();
}
......@@ -571,6 +571,9 @@ void Ia32CodeGenerator::GenCode(FunctionLiteral* fun) {
} else {
Comment cmnt(masm_, "[ declarations");
ProcessDeclarations(scope->declarations());
// Bail out if a stack-overflow exception occured when
// processing declarations.
if (HasStackOverflow()) return;
}
if (FLAG_trace) {
......@@ -3250,6 +3253,8 @@ void Ia32CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) {
// Build the function boilerplate and instantiate it.
Handle<JSFunction> boilerplate = BuildBoilerplate(node);
// Check for stack-overflow exception.
if (HasStackOverflow()) return;
InstantiateBoilerplate(boilerplate);
}
......
......@@ -115,6 +115,12 @@ Handle<JSFunction> CodeGenerator::BuildBoilerplate(FunctionLiteral* node) {
} else {
code = MakeCode(node, script_, false);
// Check for stack-overflow exception.
if (code.is_null()) {
SetStackOverflow();
return Handle<JSFunction>::null();
}
// Function compilation complete.
LOG(CodeCreateEvent("Function", *code, *node->name()));
}
......@@ -186,7 +192,10 @@ void CodeGenerator::ProcessDeclarations(ZoneList<Declaration*>* declarations) {
array->set_undefined(j++);
}
} else {
array->set(j++, *BuildBoilerplate(node->fun()));
Handle<JSFunction> function = BuildBoilerplate(node->fun());
// Check for stack-overflow exception.
if (HasStackOverflow()) return;
array->set(j++, *function);
}
}
}
......
......@@ -77,7 +77,8 @@ static Handle<Code> MakeCode(FunctionLiteral* literal,
// Rewrite the AST by introducing .result assignments where needed.
if (!Rewriter::Process(literal) || !AnalyzeVariableUsage(literal)) {
Top::StackOverflow();
// Signal a stack overflow by returning a null handle. The stack
// overflow exception will be thrown by the caller.
return Handle<Code>::null();
}
......@@ -122,6 +123,13 @@ static Handle<JSFunction> MakeFunction(bool is_global,
// Build AST.
FunctionLiteral* lit = MakeAST(is_global, script, extension, pre_data);
// Check for parse errors.
if (lit == NULL) {
ASSERT(Top::has_pending_exception());
StackGuard::EnableInterrupts();
return Handle<JSFunction>::null();
}
// Measure how long it takes to do the compilation; only take the
// rest of the function into account to avoid overlap with the
// parsing statistics.
......@@ -131,12 +139,11 @@ static Handle<JSFunction> MakeFunction(bool is_global,
StatsRateScope timer(rate);
// Compile the code.
Handle<Code> code = Handle<Code>::null();
if (lit != NULL) code = MakeCode(lit, script, is_eval);
Handle<Code> code = MakeCode(lit, script, is_eval);
// Check for stack overflow.
// Check for stack-overflow exceptions.
if (code.is_null()) {
ASSERT(Top::has_pending_exception());
Top::StackOverflow();
StackGuard::EnableInterrupts();
return Handle<JSFunction>::null();
}
......@@ -253,18 +260,24 @@ bool Compiler::CompileLazy(Handle<SharedFunctionInfo> shared) {
end_position,
is_expression);
// Check for parse errors.
if (lit == NULL) {
ASSERT(Top::has_pending_exception());
StackGuard::EnableInterrupts();
return false;
}
// Measure how long it takes to do the lazy compilation; only take
// the rest of the function into account to avoid overlap with the
// lazy parsing statistics.
StatsRateScope timer(&Counters::compile_lazy);
// Compile the code (if we have a syntax tree).
Handle<Code> code = Handle<Code>::null();
if (lit != NULL) code = MakeCode(lit, script, false);
// Compile the code.
Handle<Code> code = MakeCode(lit, script, false);
// Check for stack-overflow during compilation.
// Check for stack-overflow exception.
if (code.is_null()) {
ASSERT(Top::has_pending_exception());
Top::StackOverflow();
StackGuard::EnableInterrupts();
return false;
}
......
......@@ -578,9 +578,7 @@ bool Debug::CompileDebuggerScript(int index) {
bool Debug::Load() {
// Return if debugger is already loaded.
if (IsLoaded()) {
return true;
}
if (IsLoaded()) return true;
// Create the debugger context.
HandleScope scope;
......@@ -1499,17 +1497,20 @@ Handle<String> Debugger::ProcessRequest(Handle<Object> exec_state,
// Call ProcessDebugRequest expect String result. The ProcessDebugRequest
// will never throw an exception (see debug.js).
bool has_pending_exception = false;
bool caught_exception;
const int argc = 3;
Object** argv[argc] = { exec_state.location(),
request.location(),
stopped ? Factory::true_value().location() :
Factory::false_value().location()};
Handle<Object> result = Execution::Call(process_denbug_request,
Handle<Object> result = Execution::TryCall(process_denbug_request,
Factory::undefined_value(),
argc, argv,
&has_pending_exception);
ASSERT(!has_pending_exception);
&caught_exception);
if (caught_exception) {
return Factory::empty_symbol();
}
return Handle<String>::cast(result);
}
......@@ -1522,14 +1523,17 @@ bool Debugger::IsPlainBreakRequest(Handle<Object> request) {
*Factory::LookupAsciiSymbol("IsPlainBreakRequest"))));
// Call ProcessDebugRequest expect String result.
bool has_pending_exception = false;
bool caught_exception;
const int argc = 1;
Object** argv[argc] = { request.location() };
Handle<Object> result = Execution::Call(process_denbug_request,
Handle<Object> result = Execution::TryCall(process_denbug_request,
Factory::undefined_value(),
argc, argv,
&has_pending_exception);
ASSERT(!has_pending_exception);
&caught_exception);
if (caught_exception) {
return false;
}
return *result == Heap::true_value();
}
......@@ -1551,7 +1555,8 @@ void Debugger::OnException(Handle<Object> exception, bool uncaught) {
if (!Debug::break_on_exception()) return;
}
// Enter the debugger.
// Enter the debugger. Bail out if the debugger cannot be loaded.
if (!Debug::Load()) return;
SaveBreakFrame save;
EnterDebuggerContext enter;
......@@ -1579,6 +1584,9 @@ void Debugger::OnException(Handle<Object> exception, bool uncaught) {
void Debugger::OnDebugBreak(Handle<Object> break_points_hit) {
HandleScope scope;
// Debugger has already been entered by caller.
ASSERT(Top::context() == *Debug::debug_context());
// Bail out if there is no listener for this event
if (!Debugger::EventActive(v8::Break)) return;
......@@ -1611,8 +1619,8 @@ void Debugger::OnBeforeCompile(Handle<Script> script) {
if (compiling_natives()) return;
if (!EventActive(v8::BeforeCompile)) return;
// Enter the debugger.
Debug::Load();
// Enter the debugger. Bail out if the debugger cannot be loaded.
if (!Debug::Load()) return;
SaveBreakFrame save;
EnterDebuggerContext enter;
......@@ -1633,15 +1641,18 @@ void Debugger::OnBeforeCompile(Handle<Script> script) {
// Handle debugger actions when a new script is compiled.
void Debugger::OnAfterCompile(Handle<Script> script, Handle<JSFunction> fun) {
HandleScope scope;
// No compile events while compiling natives.
if (compiling_natives()) return;
// No more to do if not debugging.
if (!debugger_active()) return;
HandleScope scope;
// Enter the debugger. Bail out if the debugger cannot be loaded.
if (!Debug::Load()) return;
SaveBreakFrame save;
EnterDebuggerContext enter;
bool caught_exception = false;
// If debugging there might be script break points registered for this
// script. Make sure that these break points are set.
......@@ -1660,6 +1671,7 @@ void Debugger::OnAfterCompile(Handle<Script> script, Handle<JSFunction> fun) {
Handle<JSValue> wrapper = GetScriptWrapper(script);
// Call UpdateScriptBreakPoints expect no exceptions.
bool caught_exception = false;
const int argc = 1;
Object** argv[argc] = { reinterpret_cast<Object**>(wrapper.location()) };
Handle<Object> result = Execution::TryCall(
......@@ -1697,7 +1709,8 @@ void Debugger::OnNewFunction(Handle<JSFunction> function) {
if (compiling_natives()) return;
if (!Debugger::EventActive(v8::NewFunction)) return;
// Enter the debugger.
// Enter the debugger. Bail out if the debugger cannot be loaded.
if (!Debug::Load()) return;
SaveBreakFrame save;
EnterDebuggerContext enter;
......@@ -1954,9 +1967,7 @@ void DebugMessageThread::Run() {
void DebugMessageThread::DebugEvent(v8::DebugEvent event,
Handle<Object> exec_state,
Handle<Object> event_data) {
if (!Debug::Load()) {
return;
}
if (!Debug::Load()) return;
// Process the individual events.
bool interactive = false;
......
......@@ -619,18 +619,27 @@ Handle<JSFunction> Factory::CreateApiFunction(
bool is_global) {
Handle<Code> code = Handle<Code>(Builtins::builtin(Builtins::HandleApiCall));
int internal_field_count = Smi::cast(obj->internal_field_count())->value();
int size = kPointerSize * internal_field_count;
int internal_field_count = 0;
if (!obj->instance_template()->IsUndefined()) {
Handle<ObjectTemplateInfo> instance_template =
Handle<ObjectTemplateInfo>(
ObjectTemplateInfo::cast(obj->instance_template()));
internal_field_count =
Smi::cast(instance_template->internal_field_count())->value();
}
int instance_size = kPointerSize * internal_field_count;
if (is_global) {
size += JSGlobalObject::kSize;
instance_size += JSGlobalObject::kSize;
} else {
size += JSObject::kHeaderSize;
instance_size += JSObject::kHeaderSize;
}
InstanceType type = is_global ? JS_GLOBAL_OBJECT_TYPE : JS_OBJECT_TYPE;
Handle<JSFunction> result =
Factory::NewFunction(Factory::empty_symbol(), type, size, code, true);
Factory::NewFunction(Factory::empty_symbol(), type, instance_size,
code, true);
// Set class name.
Handle<Object> class_name = Handle<Object>(obj->class_name());
if (class_name->IsString()) {
......
......@@ -37,13 +37,13 @@ const DONT_DELETE = 4;
const GETTER = 0;
const SETTER = 1;
# These definitions must match the constants defined in v9.h
# These definitions must match the index of the properties in objects.h.
const kApiTagOffset = 0;
const kApiPropertyListOffset = 1;
const kApiSerialNumberOffset = 2;
const kApiConstructorOffset = 2;
const kApiPrototypeTemplateOffset = 6;
const kApiParentTemplateOffset = 7;
const kApiPrototypeTemplateOffset = 5;
const kApiParentTemplateOffset = 6;
const NO_HINT = 0;
const NUMBER_HINT = 1;
......
......@@ -757,7 +757,6 @@ void FunctionTemplateInfo::FunctionTemplateInfoVerify() {
TemplateInfoVerify();
VerifyPointer(serial_number());
VerifyPointer(call_code());
VerifyPointer(internal_field_count());
VerifyPointer(property_accessors());
VerifyPointer(prototype_template());
VerifyPointer(parent_template());
......@@ -778,8 +777,6 @@ void FunctionTemplateInfo::FunctionTemplateInfoPrint() {
serial_number()->ShortPrint();
PrintF("\n - call_code: ");
call_code()->ShortPrint();
PrintF("\n - internal_field_count: ");
internal_field_count()->ShortPrint();
PrintF("\n - property_accessors: ");
property_accessors()->ShortPrint();
PrintF("\n - prototype_template: ");
......@@ -805,12 +802,15 @@ void ObjectTemplateInfo::ObjectTemplateInfoVerify() {
CHECK(IsObjectTemplateInfo());
TemplateInfoVerify();
VerifyPointer(constructor());
VerifyPointer(internal_field_count());
}
void ObjectTemplateInfo::ObjectTemplateInfoPrint() {
PrintF("ObjectTemplateInfo");
PrintF("\n - constructor");
PrintF("\n - constructor: ");
constructor()->ShortPrint();
PrintF("\n - internal_field_count: ");
internal_field_count()->ShortPrint();
}
void SignatureInfo::SignatureInfoVerify() {
......@@ -821,9 +821,9 @@ void SignatureInfo::SignatureInfoVerify() {
void SignatureInfo::SignatureInfoPrint() {
PrintF("SignatureInfo");
PrintF("\n - receiver");
PrintF("\n - receiver: ");
receiver()->ShortPrint();
PrintF("\n - args");
PrintF("\n - args: ");
args()->ShortPrint();
}
......@@ -834,7 +834,7 @@ void TypeSwitchInfo::TypeSwitchInfoVerify() {
void TypeSwitchInfo::TypeSwitchInfoPrint() {
PrintF("TypeSwitchInfo");
PrintF("\n - types");
PrintF("\n - types: ");
types()->ShortPrint();
}
......
......@@ -1522,8 +1522,6 @@ ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset)
ACCESSORS(FunctionTemplateInfo, serial_number, Object, kSerialNumberOffset)
ACCESSORS(FunctionTemplateInfo, call_code, Object, kCallCodeOffset)
ACCESSORS(FunctionTemplateInfo, internal_field_count, Object,
kInternalFieldCountOffset)
ACCESSORS(FunctionTemplateInfo, property_accessors, Object,
kPropertyAccessorsOffset)
ACCESSORS(FunctionTemplateInfo, prototype_template, Object,
......@@ -1545,6 +1543,8 @@ ACCESSORS(FunctionTemplateInfo, access_check_info, Object,
ACCESSORS(FunctionTemplateInfo, flag, Smi, kFlagOffset)
ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset)
ACCESSORS(ObjectTemplateInfo, internal_field_count, Object,
kInternalFieldCountOffset)
ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset)
ACCESSORS(SignatureInfo, args, Object, kArgsOffset)
......
......@@ -3326,7 +3326,6 @@ class FunctionTemplateInfo: public TemplateInfo {
public:
DECL_ACCESSORS(serial_number, Object)
DECL_ACCESSORS(call_code, Object)
DECL_ACCESSORS(internal_field_count, Object)
DECL_ACCESSORS(property_accessors, Object)
DECL_ACCESSORS(prototype_template, Object)
DECL_ACCESSORS(parent_template, Object)
......@@ -3356,9 +3355,7 @@ class FunctionTemplateInfo: public TemplateInfo {
static const int kSerialNumberOffset = TemplateInfo::kHeaderSize;
static const int kCallCodeOffset = kSerialNumberOffset + kPointerSize;
static const int kInternalFieldCountOffset = kCallCodeOffset + kPointerSize;
static const int kPropertyAccessorsOffset =
kInternalFieldCountOffset + kPointerSize;
static const int kPropertyAccessorsOffset = kCallCodeOffset + kPointerSize;
static const int kPrototypeTemplateOffset =
kPropertyAccessorsOffset + kPointerSize;
static const int kParentTemplateOffset =
......@@ -3392,6 +3389,7 @@ class FunctionTemplateInfo: public TemplateInfo {
class ObjectTemplateInfo: public TemplateInfo {
public:
DECL_ACCESSORS(constructor, Object)
DECL_ACCESSORS(internal_field_count, Object)
static inline ObjectTemplateInfo* cast(Object* obj);
......@@ -3401,7 +3399,9 @@ class ObjectTemplateInfo: public TemplateInfo {
#endif
static const int kConstructorOffset = TemplateInfo::kHeaderSize;
static const int kSize = kConstructorOffset + kHeaderSize;
static const int kInternalFieldCountOffset =
kConstructorOffset + kPointerSize;
static const int kSize = kInternalFieldCountOffset + kHeaderSize;
};
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment