Version 5.1.281.52 (cherry-pick)

Merged b3d793e48ab513b964d3e21be81f6b6713854ab2

[api] Introduce ReturnValue::Get

R=hablich@chromium.org
BUG=chromium:601073

Review URL: https://codereview.chromium.org/2026443002 .

Cr-Commit-Position: refs/branch-heads/5.1@{#63}
Cr-Branched-From: 167dc63b4c9a1d0f0fe1b19af93644ac9a561e83-refs/heads/5.1.281@{#1}
Cr-Branched-From: 03953f52bd4a184983a551927c406be6489ef89b-refs/heads/master@{#35282}
diff --git a/include/v8-version.h b/include/v8-version.h
index f192295..5b23069 100644
--- a/include/v8-version.h
+++ b/include/v8-version.h
@@ -11,7 +11,7 @@
 #define V8_MAJOR_VERSION 5
 #define V8_MINOR_VERSION 1
 #define V8_BUILD_NUMBER 281
-#define V8_PATCH_LEVEL 51
+#define V8_PATCH_LEVEL 52
 
 // Use 1 for candidates and 0 otherwise.
 // (Boolean macro values are not supported by all preprocessors.)
diff --git a/include/v8.h b/include/v8.h
index ca99bef..703a4f4 100644
--- a/include/v8.h
+++ b/include/v8.h
@@ -330,6 +330,8 @@
   template <class F1, class F2, class F3>
   friend class PersistentValueMapBase;
   template<class F1, class F2> friend class PersistentValueVector;
+  template <class F>
+  friend class ReturnValue;
 
   explicit V8_INLINE Local(T* that) : val_(that) {}
   V8_INLINE static Local<T> New(Isolate* isolate, T* that);
@@ -3136,12 +3138,17 @@
   V8_INLINE void SetUndefined();
   V8_INLINE void SetEmptyString();
   // Convenience getter for Isolate
-  V8_INLINE Isolate* GetIsolate();
+  V8_INLINE Isolate* GetIsolate() const;
 
   // Pointer setter: Uncompilable to prevent inadvertent misuse.
   template <typename S>
   V8_INLINE void Set(S* whatever);
 
+  // Getter. Creates a new Local<> so it comes with a certain performance
+  // hit. If the ReturnValue was not yet set, this will return the undefined
+  // value.
+  V8_INLINE Local<Value> Get() const;
+
  private:
   template<class F> friend class ReturnValue;
   template<class F> friend class FunctionCallbackInfo;
@@ -7343,6 +7350,7 @@
       kAmountOfExternalAllocatedMemoryAtLastGlobalGCOffset + kApiInt64Size +
       kApiPointerSize;
   static const int kUndefinedValueRootIndex = 4;
+  static const int kTheHoleValueRootIndex = 5;
   static const int kNullValueRootIndex = 6;
   static const int kTrueValueRootIndex = 7;
   static const int kFalseValueRootIndex = 8;
@@ -7822,14 +7830,22 @@
   *value_ = *I::GetRoot(GetIsolate(), I::kEmptyStringRootIndex);
 }
 
-template<typename T>
-Isolate* ReturnValue<T>::GetIsolate() {
+template <typename T>
+Isolate* ReturnValue<T>::GetIsolate() const {
   // Isolate is always the pointer below the default value on the stack.
   return *reinterpret_cast<Isolate**>(&value_[-2]);
 }
 
-template<typename T>
-template<typename S>
+template <typename T>
+Local<Value> ReturnValue<T>::Get() const {
+  typedef internal::Internals I;
+  if (*value_ == *I::GetRoot(GetIsolate(), I::kTheHoleValueRootIndex))
+    return Local<Value>(*Undefined(GetIsolate()));
+  return Local<Value>::New(GetIsolate(), reinterpret_cast<Value*>(value_));
+}
+
+template <typename T>
+template <typename S>
 void ReturnValue<T>::Set(S* whatever) {
   // Uncompilable to prevent inadvertent misuse.
   TYPE_CHECK(S*, Primitive);
diff --git a/src/heap/heap.h b/src/heap/heap.h
index f6b49a3..9457453 100644
--- a/src/heap/heap.h
+++ b/src/heap/heap.h
@@ -551,6 +551,7 @@
 
   STATIC_ASSERT(kUndefinedValueRootIndex ==
                 Internals::kUndefinedValueRootIndex);
+  STATIC_ASSERT(kTheHoleValueRootIndex == Internals::kTheHoleValueRootIndex);
   STATIC_ASSERT(kNullValueRootIndex == Internals::kNullValueRootIndex);
   STATIC_ASSERT(kTrueValueRootIndex == Internals::kTrueValueRootIndex);
   STATIC_ASSERT(kFalseValueRootIndex == Internals::kFalseValueRootIndex);
diff --git a/test/cctest/test-api.h b/test/cctest/test-api.h
index 379fe9c..8887a8a 100644
--- a/test/cctest/test-api.h
+++ b/test/cctest/test-api.h
@@ -18,6 +18,12 @@
   CHECK((*o)->IsTheHole() || (*o)->IsUndefined());
   // Verify reset
   bool is_runtime = (*o)->IsTheHole();
+  if (is_runtime) {
+    CHECK(rv.Get()->IsUndefined());
+  } else {
+    i::Handle<i::Object> v = v8::Utils::OpenHandle(*rv.Get());
+    CHECK_EQ(*v, *o);
+  }
   rv.Set(true);
   CHECK(!(*o)->IsTheHole() && !(*o)->IsUndefined());
   rv.Set(v8::Local<v8::Object>());