Revision: 12450
Author: [email protected]
Date: Wed Sep 5 13:04:15 2012
Log: Merged r12440, r12441, r12445, r12446, r12443 into 3.12 branch.
Add build system infrastructure for ENABLE_EXTRA_CHECKS flag (not used yet)
Fix missing colon in common.gypi
Add empty-handle checks to API functions (#ifdef ENABLE_EXTRA_CHECKS)
Check the return value of API calls on ia32 and x64.
Push stacktrace and die if the receiver is of unknown type.
[email protected]
Review URL: https://chromiumcodereview.appspot.com/10914103
http://code.google.com/p/v8/source/detail?r=12450
Modified:
/branches/3.12/Makefile
/branches/3.12/build/common.gypi
/branches/3.12/src/api.cc
/branches/3.12/src/api.h
/branches/3.12/src/checks.h
/branches/3.12/src/ia32/macro-assembler-ia32.cc
/branches/3.12/src/isolate.cc
/branches/3.12/src/isolate.h
/branches/3.12/src/objects.cc
/branches/3.12/src/x64/macro-assembler-x64.cc
=======================================
--- /branches/3.12/Makefile Mon Jul 30 06:05:33 2012
+++ /branches/3.12/Makefile Wed Sep 5 13:04:15 2012
@@ -61,6 +61,13 @@
ifeq ($(snapshot), off)
GYPFLAGS += -Dv8_use_snapshot='false'
endif
+# extrachecks=on/off
+ifeq ($(extrachecks), on)
+ GYPFLAGS += -Dv8_enable_extra_checks=1
+endif
+ifeq ($(extrachecks), off)
+ GYPFLAGS += -Dv8_enable_extra_checks=0
+endif
# gdbjit=on
ifeq ($(gdbjit), on)
GYPFLAGS += -Dv8_enable_gdbjit=1
=======================================
--- /branches/3.12/build/common.gypi Fri Jul 27 01:03:27 2012
+++ /branches/3.12/build/common.gypi Wed Sep 5 13:04:15 2012
@@ -70,6 +70,9 @@
'v8_enable_disassembler%': 0,
+ # Enable extra checks in API functions and other strategic places.
+ 'v8_enable_extra_checks%': 1,
+
'v8_object_print%': 0,
'v8_enable_gdbjit%': 0,
@@ -109,6 +112,9 @@
['v8_enable_disassembler==1', {
'defines': ['ENABLE_DISASSEMBLER',],
}],
+ ['v8_enable_extra_checks==1', {
+ 'defines': ['ENABLE_EXTRA_CHECKS',],
+ }],
['v8_object_print==1', {
'defines': ['OBJECT_PRINT',],
}],
=======================================
--- /branches/3.12/src/api.cc Wed Aug 1 04:14:42 2012
+++ /branches/3.12/src/api.cc Wed Sep 5 13:04:15 2012
@@ -1540,7 +1540,7 @@
column_offset,
NULL,
pre_data_impl,
- Utils::OpenHandle(*script_data),
+ Utils::OpenHandle(*script_data, true),
i::NOT_NATIVES_CODE);
has_pending_exception = result.is_null();
EXCEPTION_BAILOUT_CHECK(isolate, Local<Script>());
@@ -4394,7 +4394,7 @@
// Create the environment.
env = isolate->bootstrapper()->CreateEnvironment(
isolate,
- Utils::OpenHandle(*global_object),
+ Utils::OpenHandle(*global_object, true),
proxy_template,
extensions);
@@ -5625,7 +5625,8 @@
foreign =
isolate->factory()->NewForeign(FUNCTION_ADDR(EventCallbackWrapper));
}
- isolate->debugger()->SetEventListener(foreign, Utils::OpenHandle(*data));
+ isolate->debugger()->SetEventListener(foreign,
+ Utils::OpenHandle(*data, true));
return true;
}
@@ -5640,7 +5641,8 @@
if (that != NULL) {
foreign = isolate->factory()->NewForeign(FUNCTION_ADDR(that));
}
- isolate->debugger()->SetEventListener(foreign, Utils::OpenHandle(*data));
+ isolate->debugger()->SetEventListener(foreign,
+ Utils::OpenHandle(*data, true));
return true;
}
@@ -5651,7 +5653,7 @@
ON_BAILOUT(isolate, "v8::Debug::SetDebugEventListener()", return false);
ENTER_V8(isolate);
isolate->debugger()->SetEventListener(Utils::OpenHandle(*that),
-
Utils::OpenHandle(*data));
+ Utils::OpenHandle(*data, true));
return true;
}
=======================================
--- /branches/3.12/src/api.h Tue Jul 24 00:59:48 2012
+++ /branches/3.12/src/api.h Wed Sep 5 13:04:15 2012
@@ -159,6 +159,27 @@
};
+#define OPEN_HANDLE_LIST(V) \
+ V(Template, TemplateInfo) \
+ V(FunctionTemplate, FunctionTemplateInfo) \
+ V(ObjectTemplate, ObjectTemplateInfo) \
+ V(Signature, SignatureInfo) \
+ V(AccessorSignature, FunctionTemplateInfo) \
+ V(TypeSwitch, TypeSwitchInfo) \
+ V(Data, Object) \
+ V(RegExp, JSRegExp) \
+ V(Object, JSObject) \
+ V(Array, JSArray) \
+ V(String, String) \
+ V(Script, Object) \
+ V(Function, JSFunction) \
+ V(Message, JSObject) \
+ V(Context, Context) \
+ V(External, Foreign) \
+ V(StackTrace, JSArray) \
+ V(StackFrame, JSObject)
+
+
class Utils {
public:
static bool ReportApiFailure(const char* location, const char* message);
@@ -205,42 +226,13 @@
static inline Local<TypeSwitch> ToLocal(
v8::internal::Handle<v8::internal::TypeSwitchInfo> obj);
- static inline v8::internal::Handle<v8::internal::TemplateInfo>
- OpenHandle(const Template* that);
- static inline v8::internal::Handle<v8::internal::FunctionTemplateInfo>
- OpenHandle(const FunctionTemplate* that);
- static inline v8::internal::Handle<v8::internal::ObjectTemplateInfo>
- OpenHandle(const ObjectTemplate* that);
- static inline v8::internal::Handle<v8::internal::Object>
- OpenHandle(const Data* data);
- static inline v8::internal::Handle<v8::internal::JSRegExp>
- OpenHandle(const RegExp* data);
- static inline v8::internal::Handle<v8::internal::JSObject>
- OpenHandle(const v8::Object* data);
- static inline v8::internal::Handle<v8::internal::JSArray>
- OpenHandle(const v8::Array* data);
- static inline v8::internal::Handle<v8::internal::String>
- OpenHandle(const String* data);
- static inline v8::internal::Handle<v8::internal::Object>
- OpenHandle(const Script* data);
- static inline v8::internal::Handle<v8::internal::JSFunction>
- OpenHandle(const Function* data);
- static inline v8::internal::Handle<v8::internal::JSObject>
- OpenHandle(const Message* message);
- static inline v8::internal::Handle<v8::internal::JSArray>
- OpenHandle(const StackTrace* stack_trace);
- static inline v8::internal::Handle<v8::internal::JSObject>
- OpenHandle(const StackFrame* stack_frame);
- static inline v8::internal::Handle<v8::internal::Context>
- OpenHandle(const v8::Context* context);
- static inline v8::internal::Handle<v8::internal::SignatureInfo>
- OpenHandle(const v8::Signature* sig);
- static inline v8::internal::Handle<v8::internal::FunctionTemplateInfo>
- OpenHandle(const v8::AccessorSignature* sig);
- static inline v8::internal::Handle<v8::internal::TypeSwitchInfo>
- OpenHandle(const v8::TypeSwitch* that);
- static inline v8::internal::Handle<v8::internal::Foreign>
- OpenHandle(const v8::External* that);
+#define DECLARE_OPEN_HANDLE(From, To) \
+ static inline v8::internal::Handle<v8::internal::To> \
+ OpenHandle(const From* that, bool allow_empty_handle = false);
+
+OPEN_HANDLE_LIST(DECLARE_OPEN_HANDLE)
+
+#undef DECLARE_OPEN_HANDLE
};
@@ -257,7 +249,7 @@
if (!is_null()) {
handle = *this;
}
- return Utils::OpenHandle(*scope->Close(Utils::ToLocal(handle)));
+ return Utils::OpenHandle(*scope->Close(Utils::ToLocal(handle)), true);
}
@@ -294,33 +286,18 @@
// Implementations of OpenHandle
-#define MAKE_OPEN_HANDLE(From, To) \
- v8::internal::Handle<v8::internal::To> Utils::OpenHandle(\
- const v8::From* that) { \
- return v8::internal::Handle<v8::internal::To>( \
+#define MAKE_OPEN_HANDLE(From,
To) \
+ v8::internal::Handle<v8::internal::To>
Utils::OpenHandle( \
+ const v8::From* that, bool allow_empty_handle)
{ \
+ EXTRA_CHECK(allow_empty_handle || that !=
NULL); \
+ return
v8::internal::Handle<v8::internal::To>( \
reinterpret_cast<v8::internal::To**>(const_cast<v8::From*>(that))); \
}
-MAKE_OPEN_HANDLE(Template, TemplateInfo)
-MAKE_OPEN_HANDLE(FunctionTemplate, FunctionTemplateInfo)
-MAKE_OPEN_HANDLE(ObjectTemplate, ObjectTemplateInfo)
-MAKE_OPEN_HANDLE(Signature, SignatureInfo)
-MAKE_OPEN_HANDLE(AccessorSignature, FunctionTemplateInfo)
-MAKE_OPEN_HANDLE(TypeSwitch, TypeSwitchInfo)
-MAKE_OPEN_HANDLE(Data, Object)
-MAKE_OPEN_HANDLE(RegExp, JSRegExp)
-MAKE_OPEN_HANDLE(Object, JSObject)
-MAKE_OPEN_HANDLE(Array, JSArray)
-MAKE_OPEN_HANDLE(String, String)
-MAKE_OPEN_HANDLE(Script, Object)
-MAKE_OPEN_HANDLE(Function, JSFunction)
-MAKE_OPEN_HANDLE(Message, JSObject)
-MAKE_OPEN_HANDLE(Context, Context)
-MAKE_OPEN_HANDLE(External, Foreign)
-MAKE_OPEN_HANDLE(StackTrace, JSArray)
-MAKE_OPEN_HANDLE(StackFrame, JSObject)
+OPEN_HANDLE_LIST(MAKE_OPEN_HANDLE)
#undef MAKE_OPEN_HANDLE
+#undef OPEN_HANDLE_LIST
namespace internal {
=======================================
--- /branches/3.12/src/checks.h Wed Feb 1 02:48:36 2012
+++ /branches/3.12/src/checks.h Wed Sep 5 13:04:15 2012
@@ -284,4 +284,12 @@
#define ASSERT_NOT_NULL(p) ASSERT_NE(NULL, p)
+// "Extra checks" are lightweight checks that are enabled in some release
+// builds.
+#ifdef ENABLE_EXTRA_CHECKS
+#define EXTRA_CHECK(condition) CHECK(condition)
+#else
+#define EXTRA_CHECK(condition) ((void) 0)
+#endif
+
#endif // V8_CHECKS_H_
=======================================
--- /branches/3.12/src/ia32/macro-assembler-ia32.cc Wed Aug 1 04:14:42 2012
+++ /branches/3.12/src/ia32/macro-assembler-ia32.cc Wed Sep 5 13:04:15 2012
@@ -1922,6 +1922,42 @@
cmp(Operand::StaticVariable(scheduled_exception_address),
Immediate(isolate()->factory()->the_hole_value()));
j(not_equal, &promote_scheduled_exception);
+
+#if ENABLE_EXTRA_CHECKS
+ // Check if the function returned a valid JavaScript value.
+ Label ok;
+ Register return_value = eax;
+ Register map = ecx;
+
+ JumpIfSmi(return_value, &ok, Label::kNear);
+ mov(map, FieldOperand(return_value, HeapObject::kMapOffset));
+
+ CmpInstanceType(map, FIRST_NONSTRING_TYPE);
+ j(below, &ok, Label::kNear);
+
+ CmpInstanceType(map, FIRST_SPEC_OBJECT_TYPE);
+ j(above_equal, &ok, Label::kNear);
+
+ cmp(map, isolate()->factory()->heap_number_map());
+ j(equal, &ok, Label::kNear);
+
+ cmp(return_value, isolate()->factory()->undefined_value());
+ j(equal, &ok, Label::kNear);
+
+ cmp(return_value, isolate()->factory()->true_value());
+ j(equal, &ok, Label::kNear);
+
+ cmp(return_value, isolate()->factory()->false_value());
+ j(equal, &ok, Label::kNear);
+
+ cmp(return_value, isolate()->factory()->null_value());
+ j(equal, &ok, Label::kNear);
+
+ Abort("API call returned invalid object");
+
+ bind(&ok);
+#endif
+
LeaveApiExitFrame();
ret(stack_space * kPointerSize);
=======================================
--- /branches/3.12/src/isolate.cc Wed Aug 1 04:14:42 2012
+++ /branches/3.12/src/isolate.cc Wed Sep 5 13:04:15 2012
@@ -533,6 +533,24 @@
return factory()->empty_symbol();
}
}
+
+
+void Isolate::PushStackTraceAndDie(unsigned int magic,
+ Object* object,
+ Map* map,
+ unsigned int magic2) {
+ const int kMaxStackTraceSize = 8192;
+ Handle<String> trace = StackTraceString();
+ char buffer[kMaxStackTraceSize];
+ int length = Min(kMaxStackTraceSize - 1, trace->length());
+ String::WriteToFlat(*trace, buffer, 0, length);
+ buffer[length] = '\0';
+ OS::PrintError("Stacktrace (%x-%x) %p %p: %s\n",
+ magic, magic2,
+ static_cast<void*>(object), static_cast<void*>(map),
+ buffer);
+ OS::Abort();
+}
void Isolate::CaptureAndSetCurrentStackTraceFor(Handle<JSObject>
error_object) {
=======================================
--- /branches/3.12/src/isolate.h Tue Jul 24 00:59:48 2012
+++ /branches/3.12/src/isolate.h Wed Sep 5 13:04:15 2012
@@ -707,6 +707,10 @@
void PrintStack(StringStream* accumulator);
void PrintStack();
Handle<String> StackTraceString();
+ NO_INLINE(void PushStackTraceAndDie(unsigned int magic,
+ Object* object,
+ Map* map,
+ unsigned int magic2));
Handle<JSArray> CaptureCurrentStackTrace(
int frame_limit,
StackTrace::StackTraceOptions options);
=======================================
--- /branches/3.12/src/objects.cc Tue Aug 21 01:56:54 2012
+++ /branches/3.12/src/objects.cc Wed Sep 5 13:04:15 2012
@@ -141,6 +141,9 @@
holder = global_context->string_function()->instance_prototype();
} else if (IsBoolean()) {
holder = global_context->boolean_function()->instance_prototype();
+ } else {
+ Isolate::Current()->PushStackTraceAndDie(
+ 0xDEAD0000, this, JSReceiver::cast(this)->map(), 0xDEAD0001);
}
}
ASSERT(holder != NULL); // Cannot handle null or undefined.
@@ -206,7 +209,20 @@
if (result.IsEmpty()) {
return isolate->heap()->undefined_value();
}
- return *v8::Utils::OpenHandle(*result);
+ Object* return_value = *v8::Utils::OpenHandle(*result);
+#if ENABLE_EXTRA_CHECKS
+ if (!(return_value->IsSmi() ||
+ return_value->IsString() ||
+ return_value->IsSpecObject() ||
+ return_value->IsHeapNumber() ||
+ return_value->IsUndefined() ||
+ return_value->IsTrue() ||
+ return_value->IsFalse() ||
+ return_value->IsNull())) {
+ FATAL("API call returned invalid object");
+ }
+#endif
+ return return_value;
}
// __defineGetter__ callback
=======================================
--- /branches/3.12/src/x64/macro-assembler-x64.cc Wed Aug 1 04:14:42 2012
+++ /branches/3.12/src/x64/macro-assembler-x64.cc Wed Sep 5 13:04:15 2012
@@ -751,6 +751,41 @@
Cmp(Operand(rsi, 0), factory->the_hole_value());
j(not_equal, &promote_scheduled_exception);
+#if ENABLE_EXTRA_CHECKS
+ // Check if the function returned a valid JavaScript value.
+ Label ok;
+ Register return_value = rax;
+ Register map = rcx;
+
+ JumpIfSmi(return_value, &ok, Label::kNear);
+ movq(map, FieldOperand(return_value, HeapObject::kMapOffset));
+
+ CmpInstanceType(map, FIRST_NONSTRING_TYPE);
+ j(below, &ok, Label::kNear);
+
+ CmpInstanceType(map, FIRST_SPEC_OBJECT_TYPE);
+ j(above_equal, &ok, Label::kNear);
+
+ CompareRoot(map, Heap::kHeapNumberMapRootIndex);
+ j(equal, &ok, Label::kNear);
+
+ CompareRoot(return_value, Heap::kUndefinedValueRootIndex);
+ j(equal, &ok, Label::kNear);
+
+ CompareRoot(return_value, Heap::kTrueValueRootIndex);
+ j(equal, &ok, Label::kNear);
+
+ CompareRoot(return_value, Heap::kFalseValueRootIndex);
+ j(equal, &ok, Label::kNear);
+
+ CompareRoot(return_value, Heap::kNullValueRootIndex);
+ j(equal, &ok, Label::kNear);
+
+ Abort("API call returned invalid object");
+
+ bind(&ok);
+#endif
+
LeaveApiExitFrame();
ret(stack_space * kPointerSize);
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev