Revision: 20457
Author: [email protected]
Date: Thu Apr 3 05:57:43 2014 UTC
Log: Introduce MaybeHandle to police exception checking in handlified
code.
[email protected]
Review URL: https://codereview.chromium.org/222163002
http://code.google.com/p/v8/source/detail?r=20457
Modified:
/branches/bleeding_edge/src/handles.h
/branches/bleeding_edge/src/isolate.h
/branches/bleeding_edge/src/objects.cc
/branches/bleeding_edge/src/objects.h
/branches/bleeding_edge/src/runtime.cc
/branches/bleeding_edge/src/v8globals.h
=======================================
--- /branches/bleeding_edge/src/handles.h Fri Mar 28 09:49:27 2014 UTC
+++ /branches/bleeding_edge/src/handles.h Thu Apr 3 05:57:43 2014 UTC
@@ -34,6 +34,62 @@
namespace v8 {
namespace internal {
+// A Handle can be converted into a MaybeHandle. Converting a MaybeHandle
+// into a Handle requires checking that it does not point to NULL. This
+// ensures NULL checks before use.
+
+template<typename T>
+class MaybeHandle {
+ public:
+ INLINE(MaybeHandle()) : location_(NULL) { }
+
+ // Constructor for handling automatic up casting from Handle.
+ // Ex. Handle<JSArray> can be passed when MaybeHandle<Object> is
expected.
+ template <class S> MaybeHandle(Handle<S> handle) {
+#ifdef DEBUG
+ T* a = NULL;
+ S* b = NULL;
+ a = b; // Fake assignment to enforce type checks.
+ USE(a);
+#endif
+ this->location_ = reinterpret_cast<T**>(handle.location());
+ }
+
+ // Constructor for handling automatic up casting.
+ // Ex. MaybeHandle<JSArray> can be passed when Handle<Object> is
expected.
+ template <class S> MaybeHandle(MaybeHandle<S> maybe_handle) {
+#ifdef DEBUG
+ T* a = NULL;
+ S* b = NULL;
+ a = b; // Fake assignment to enforce type checks.
+ USE(a);
+#endif
+ location_ = reinterpret_cast<T**>(maybe_handle.location_);
+ }
+
+ INLINE(Handle<T> ToHandleChecked()) {
+ CHECK(location_ != NULL);
+ return Handle<T>(location_);
+ }
+
+ INLINE(bool ToHandle(Handle<T>* out)) {
+ if (location_ == NULL) {
+ *out = Handle<T>::null();
+ return false;
+ } else {
+ *out = Handle<T>(location_);
+ return true;
+ }
+ }
+
+ protected:
+ T** location_;
+
+ // MaybeHandles of different classes are allowed to access each
+ // other's location_.
+ template<class S> friend class MaybeHandle;
+};
+
//
----------------------------------------------------------------------------
// A Handle provides a reference to an object that survives relocation by
// the garbage collector.
@@ -47,7 +103,9 @@
INLINE(explicit Handle(T* obj));
INLINE(Handle(T* obj, Isolate* isolate));
- INLINE(Handle()) : location_(NULL) {}
+ // TODO(yangguo): Values that contain empty handles should be declared as
+ // MaybeHandle to force validation before being used as handles.
+ INLINE(Handle()) : location_(NULL) { }
// Constructor for handling automatic up casting.
// Ex. Handle<JSFunction> can be passed when Handle<Object> is expected.
@@ -77,6 +135,8 @@
return Handle<T>(reinterpret_cast<T**>(that.location_));
}
+ // TODO(yangguo): Values that contain empty handles should be declared as
+ // MaybeHandle to force validation before being used as handles.
static Handle<T> null() { return Handle<T>(); }
bool is_null() const { return location_ == NULL; }
=======================================
--- /branches/bleeding_edge/src/isolate.h Fri Mar 28 14:16:11 2014 UTC
+++ /branches/bleeding_edge/src/isolate.h Thu Apr 3 05:57:43 2014 UTC
@@ -134,12 +134,12 @@
} \
} while (false)
-#define RETURN_IF_EMPTY_HANDLE_VALUE(isolate, call, value) \
- do { \
- if ((call).is_null()) { \
- ASSERT((isolate)->has_pending_exception()); \
- return (value); \
- } \
+#define RETURN_IF_EMPTY_HANDLE_VALUE(isolate, call, value) \
+ do { \
+ if ((call).is_null()) { \
+ ASSERT((isolate)->has_pending_exception()); \
+ return (value); \
+ } \
} while (false)
#define CHECK_NOT_EMPTY_HANDLE(isolate, call) \
@@ -148,9 +148,51 @@
CHECK(!(call).is_null()); \
} while (false)
-#define RETURN_IF_EMPTY_HANDLE(isolate, call) \
+#define RETURN_IF_EMPTY_HANDLE(isolate, call) \
RETURN_IF_EMPTY_HANDLE_VALUE(isolate, call, Failure::Exception())
+
+// Macros for MaybeHandle.
+
+#define RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, T) \
+ do { \
+ Isolate* __isolate__ = (isolate); \
+ if (__isolate__->has_scheduled_exception()) { \
+ __isolate__->PromoteScheduledException(); \
+ return MaybeHandle<T>(); \
+ } \
+ } while (false)
+
+#define ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, dst, call, value) \
+ do { \
+ if (!(call).ToHandle(&dst)) { \
+ ASSERT((isolate)->has_pending_exception()); \
+ return value; \
+ } \
+ } while (false)
+
+#define ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, dst, call) \
+ ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, dst, call,
Failure::Exception())
+
+#define ASSIGN_RETURN_ON_EXCEPTION(isolate, dst, call, T) \
+ ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, dst, call, MaybeHandle<T>())
+
+#define RETURN_ON_EXCEPTION_VALUE(isolate, dst, call, value) \
+ do { \
+ if (call.is_null()) { \
+ ASSERT((isolate)->has_pending_exception()); \
+ return value; \
+ } \
+ } while (false)
+
+#define RETURN_FAILURE_ON_EXCEPTION(isolate, call) \
+ RETURN_ON_EXCEPTION_VALUE(isolate, dst, call, Failure::Exception())
+
+#define RETURN_ON_EXCEPTION(isolate, call, T) \
+ RETURN_ON_EXCEPTION_VALUE( \
+ isolate, dst, call, MaybeHandle<T>::Exception())
+
+
#define FOR_EACH_ISOLATE_ADDRESS_NAME(C) \
C(Handler, handler) \
C(CEntryFP, c_entry_fp) \
@@ -767,6 +809,14 @@
// Exception throwing support. The caller should use the result
// of Throw() as its return value.
Failure* Throw(Object* exception, MessageLocation* location = NULL);
+
+ template <typename T>
+ MUST_USE_RESULT MaybeHandle<T> Throw(Handle<Object> exception,
+ MessageLocation* location = NULL) {
+ Throw(*exception, location);
+ return MaybeHandle<T>();
+ }
+
// Re-throw an exception. This involves no error reporting since
// error reporting was handled when the exception was thrown
// originally.
=======================================
--- /branches/bleeding_edge/src/objects.cc Wed Apr 2 16:36:16 2014 UTC
+++ /branches/bleeding_edge/src/objects.cc Thu Apr 3 05:57:43 2014 UTC
@@ -5519,7 +5519,7 @@
}
-Handle<Object> JSObject::Freeze(Handle<JSObject> object) {
+MaybeHandle<Object> JSObject::Freeze(Handle<JSObject> object) {
// Freezing sloppy arguments should be handled elsewhere.
ASSERT(!object->HasSloppyArgumentsElements());
ASSERT(!object->map()->is_observed());
@@ -5532,7 +5532,7 @@
isolate->factory()->undefined_value(),
v8::ACCESS_KEYS)) {
isolate->ReportFailedAccessCheckWrapper(object, v8::ACCESS_KEYS);
- RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
+ RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
return isolate->factory()->false_value();
}
@@ -5550,8 +5550,7 @@
isolate->factory()->NewTypeError(
"cant_prevent_ext_external_array_elements",
HandleVector(&object, 1));
- isolate->Throw(*error);
- return Handle<Object>();
+ return isolate->Throw<Object>(error);
}
Handle<SeededNumberDictionary> new_element_dictionary;
=======================================
--- /branches/bleeding_edge/src/objects.h Wed Apr 2 16:36:16 2014 UTC
+++ /branches/bleeding_edge/src/objects.h Thu Apr 3 05:57:43 2014 UTC
@@ -2640,7 +2640,7 @@
static Handle<Object> PreventExtensions(Handle<JSObject> object);
// ES5 Object.freeze
- static Handle<Object> Freeze(Handle<JSObject> object);
+ static MaybeHandle<Object> Freeze(Handle<JSObject> object);
// Called the first time an object is observed with ES7 Object.observe.
static void SetObserved(Handle<JSObject> object);
=======================================
--- /branches/bleeding_edge/src/runtime.cc Wed Apr 2 14:47:26 2014 UTC
+++ /branches/bleeding_edge/src/runtime.cc Thu Apr 3 05:57:43 2014 UTC
@@ -3231,8 +3231,8 @@
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
- Handle<Object> result = JSObject::Freeze(object);
- RETURN_IF_EMPTY_HANDLE(isolate, result);
+ Handle<Object> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
JSObject::Freeze(object));
return *result;
}
=======================================
--- /branches/bleeding_edge/src/v8globals.h Tue Apr 1 11:07:09 2014 UTC
+++ /branches/bleeding_edge/src/v8globals.h Thu Apr 3 05:57:43 2014 UTC
@@ -128,6 +128,7 @@
class SeededNumberDictionary;
class UnseededNumberDictionary;
class NameDictionary;
+template <typename T> class MaybeHandle;
template <typename T> class Handle;
class Heap;
class HeapObject;
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.