Push revisions 1527, 1539, 1540, 1541, 1550, 1551 from bleeding_edge to trunk.

git-svn-id: http://v8.googlecode.com/svn/trunk@1555 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/api.cc b/src/api.cc
index 2a37310..785aa20 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -1919,6 +1919,88 @@
 }
 
 
+Local<v8::Object> v8::Object::Clone() {
+  ON_BAILOUT("v8::Object::Clone()", return Local<Object>());
+  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
+  EXCEPTION_PREAMBLE();
+  i::Handle<i::JSObject> result = i::Copy(self);
+  has_pending_exception = result.is_null();
+  EXCEPTION_BAILOUT_CHECK(Local<Object>());
+  return Utils::ToLocal(result);
+}
+
+
+int v8::Object::GetIdentityHash() {
+  ON_BAILOUT("v8::Object::GetIdentityHash()", return 0);
+  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
+  i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, true));
+  i::Handle<i::Object> hash_symbol = i::Factory::identity_hash_symbol();
+  i::Handle<i::Object> hash = i::GetProperty(hidden_props, hash_symbol);
+  int hash_value;
+  if (hash->IsSmi()) {
+    hash_value = i::Smi::cast(*hash)->value();
+  } else {
+    hash_value = random() & i::Smi::kMaxValue;  // Limit range to fit a smi.
+    i::SetProperty(hidden_props,
+                   hash_symbol,
+                   i::Handle<i::Object>(i::Smi::FromInt(hash_value)),
+                   static_cast<PropertyAttributes>(None));
+  }
+  return hash_value;
+}
+
+
+bool v8::Object::SetHiddenValue(v8::Handle<v8::String> key,
+                                v8::Handle<v8::Value> value) {
+  ON_BAILOUT("v8::Object::SetHiddenValue()", return false);
+  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
+  i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, true));
+  i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
+  i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
+  EXCEPTION_PREAMBLE();
+  i::Handle<i::Object> obj = i::SetProperty(
+      hidden_props,
+      key_obj,
+      value_obj,
+      static_cast<PropertyAttributes>(None));
+  has_pending_exception = obj.is_null();
+  EXCEPTION_BAILOUT_CHECK(false);
+  return true;
+}
+
+
+v8::Local<v8::Value> v8::Object::GetHiddenValue(v8::Handle<v8::String> key) {
+  ON_BAILOUT("v8::Object::GetHiddenValue()", return Local<v8::Value>());
+  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
+  i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, false));
+  if (hidden_props->IsUndefined()) {
+    return v8::Local<v8::Value>();
+  }
+  i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
+  EXCEPTION_PREAMBLE();
+  i::Handle<i::Object> result = i::GetProperty(hidden_props, key_obj);
+  has_pending_exception = result.is_null();
+  EXCEPTION_BAILOUT_CHECK(v8::Local<v8::Value>());
+  if (result->IsUndefined()) {
+    return v8::Local<v8::Value>();
+  }
+  return Utils::ToLocal(result);
+}
+
+
+bool v8::Object::DeleteHiddenValue(v8::Handle<v8::String> key) {
+  ON_BAILOUT("v8::DeleteHiddenValue()", return false);
+  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
+  i::Handle<i::JSObject> hidden_props(
+      i::JSObject::cast(*i::GetHiddenProperties(self, false)));
+  if (hidden_props->IsUndefined()) {
+    return false;
+  }
+  i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
+  return i::DeleteProperty(hidden_props, key_obj)->IsTrue();
+}
+
+
 Local<v8::Object> Function::NewInstance() const {
   return NewInstance(0, NULL);
 }
@@ -2200,7 +2282,7 @@
 
 
 const char* v8::V8::GetVersion() {
-  return "1.1.1.2";
+  return "1.1.1.3";
 }
 
 
diff --git a/src/factory.h b/src/factory.h
index 754c6da..1388de1 100644
--- a/src/factory.h
+++ b/src/factory.h
@@ -302,6 +302,10 @@
   SYMBOL_LIST(SYMBOL_ACCESSOR)
 #undef SYMBOL_ACCESSOR
 
+  static Handle<String> hidden_symbol() {
+    return Handle<String>(&Heap::hidden_symbol_);
+  }
+
   static Handle<SharedFunctionInfo> NewSharedFunctionInfo(Handle<String> name);
 
   static Handle<Dictionary> DictionaryAtNumberPut(Handle<Dictionary>,
diff --git a/src/handles.cc b/src/handles.cc
index 48065dd..b6c59b0 100644
--- a/src/handles.cc
+++ b/src/handles.cc
@@ -52,44 +52,39 @@
 }
 
 
-void** HandleScope::CreateHandle(void* value) {
+void** HandleScope::Extend() {
   void** result = current_.next;
-  if (result == current_.limit) {
-    // Make sure there's at least one scope on the stack and that the
-    // top of the scope stack isn't a barrier.
-    if (current_.extensions < 0) {
-      Utils::ReportApiFailure("v8::HandleScope::CreateHandle()",
-                              "Cannot create a handle without a HandleScope");
-      return NULL;
-    }
-    HandleScopeImplementer* impl = HandleScopeImplementer::instance();
-    // If there's more room in the last block, we use that. This is used
-    // for fast creation of scopes after scope barriers.
-    if (!impl->Blocks()->is_empty()) {
-      void** limit = &impl->Blocks()->last()[kHandleBlockSize];
-      if (current_.limit != limit) {
-        current_.limit = limit;
-      }
-    }
 
-    // If we still haven't found a slot for the handle, we extend the
-    // current handle scope by allocating a new handle block.
-    if (result == current_.limit) {
-      // If there's a spare block, use it for growing the current scope.
-      result = impl->GetSpareOrNewBlock();
-      // Add the extension to the global list of blocks, but count the
-      // extension as part of the current scope.
-      impl->Blocks()->Add(result);
-      current_.extensions++;
-      current_.limit = &result[kHandleBlockSize];
+  ASSERT(result == current_.limit);
+  // Make sure there's at least one scope on the stack and that the
+  // top of the scope stack isn't a barrier.
+  if (current_.extensions < 0) {
+    Utils::ReportApiFailure("v8::HandleScope::CreateHandle()",
+                            "Cannot create a handle without a HandleScope");
+    return NULL;
+  }
+  HandleScopeImplementer* impl = HandleScopeImplementer::instance();
+  // If there's more room in the last block, we use that. This is used
+  // for fast creation of scopes after scope barriers.
+  if (!impl->Blocks()->is_empty()) {
+    void** limit = &impl->Blocks()->last()[kHandleBlockSize];
+    if (current_.limit != limit) {
+      current_.limit = limit;
     }
   }
 
-  // Update the current next field, set the value in the created
-  // handle, and return the result.
-  ASSERT(result < current_.limit);
-  current_.next = result + 1;
-  *result = value;
+  // If we still haven't found a slot for the handle, we extend the
+  // current handle scope by allocating a new handle block.
+  if (result == current_.limit) {
+    // If there's a spare block, use it for growing the current scope.
+    result = impl->GetSpareOrNewBlock();
+    // Add the extension to the global list of blocks, but count the
+    // extension as part of the current scope.
+    impl->Blocks()->Add(result);
+    current_.extensions++;
+    current_.limit = &result[kHandleBlockSize];
+  }
+
   return result;
 }
 
@@ -266,6 +261,12 @@
 }
 
 
+Handle<Object> GetHiddenProperties(Handle<JSObject> obj,
+                                   bool create_if_needed) {
+  CALL_HEAP_FUNCTION(obj->GetHiddenProperties(create_if_needed), Object);
+}
+
+
 Handle<Object> DeleteElement(Handle<JSObject> obj,
                              uint32_t index) {
   CALL_HEAP_FUNCTION(obj->DeleteElement(index), Object);
diff --git a/src/handles.h b/src/handles.h
index 21af7fc..c8e534e 100644
--- a/src/handles.h
+++ b/src/handles.h
@@ -118,7 +118,16 @@
   static int NumberOfHandles();
 
   // Creates a new handle with the given value.
-  static void** CreateHandle(void* value);
+  static inline void** CreateHandle(void* value) {
+    void** result = current_.next;
+    if (result == current_.limit) result = Extend();
+    // Update the current next field, set the value in the created
+    // handle, and return the result.
+    ASSERT(result < current_.limit);
+    current_.next = result + 1;
+    *result = value;
+    return result;
+  }
 
  private:
   // Prevent heap allocation or illegal handle scopes.
@@ -150,6 +159,9 @@
 #endif
   }
 
+  // Extend the handle scope making room for more handles.
+  static void** Extend();
+
   // Deallocates any extensions used by the current scope.
   static void DeleteExtensions();
 
@@ -211,6 +223,8 @@
 
 Handle<Object> GetPrototype(Handle<Object> obj);
 
+Handle<Object> GetHiddenProperties(Handle<JSObject> obj, bool create_if_needed);
+
 Handle<Object> DeleteElement(Handle<JSObject> obj, uint32_t index);
 Handle<Object> DeleteProperty(Handle<JSObject> obj, Handle<String> prop);
 
diff --git a/src/heap.cc b/src/heap.cc
index 8159311..f384297 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -57,6 +57,8 @@
   SYMBOL_LIST(SYMBOL_ALLOCATION)
 #undef SYMBOL_ALLOCATION
 
+String* Heap::hidden_symbol_;
+
 NewSpace Heap::new_space_;
 OldSpace* Heap::old_pointer_space_ = NULL;
 OldSpace* Heap::old_data_space_ = NULL;
@@ -1206,6 +1208,16 @@
   SYMBOL_LIST(SYMBOL_INITIALIZE)
 #undef SYMBOL_INITIALIZE
 
+  // Allocate the hidden symbol which is used to identify the hidden properties
+  // in JSObjects. The hash code has a special value so that it will not match
+  // the empty string when searching for the property. It cannot be part of the
+  // SYMBOL_LIST because it needs to be allocated manually with the special
+  // hash code in place. The hash code for the hidden_symbol is zero to ensure
+  // that it will always be at the first entry in property descriptors.
+  obj = AllocateSymbol(CStrVector(""), 0, String::kHashComputedMask);
+  if (obj->IsFailure()) return false;
+  hidden_symbol_ = String::cast(obj);
+
   // Allocate the proxy for __proto__.
   obj = AllocateProxy((Address) &Accessors::ObjectPrototype);
   if (obj->IsFailure()) return false;
@@ -2650,6 +2662,7 @@
   v->VisitPointer(bit_cast<Object**, String**>(&name##_));
   SYMBOL_LIST(SYMBOL_ITERATE)
 #undef SYMBOL_ITERATE
+  v->VisitPointer(bit_cast<Object**, String**>(&hidden_symbol_));
   SYNCHRONIZE_TAG("symbol");
 
   Bootstrapper::Iterate(v);
diff --git a/src/heap.h b/src/heap.h
index 082bbb2..a1dd81e 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -195,7 +195,8 @@
   V(space_symbol, " ")                                                   \
   V(exec_symbol, "exec")                                                 \
   V(zero_symbol, "0")                                                    \
-  V(global_eval_symbol, "GlobalEval")
+  V(global_eval_symbol, "GlobalEval")                                    \
+  V(identity_hash_symbol, "v8::IdentityHash")
 
 
 // Forward declaration of the GCTracer class.
@@ -645,6 +646,10 @@
   SYMBOL_LIST(SYMBOL_ACCESSOR)
 #undef SYMBOL_ACCESSOR
 
+  // The hidden_symbol is special because it is the empty string, but does
+  // not match the empty string.
+  static String* hidden_symbol() { return hidden_symbol_; }
+
   // Iterates over all roots in the heap.
   static void IterateRoots(ObjectVisitor* v);
   // Iterates over all strong roots in the heap.
@@ -888,6 +893,10 @@
   SYMBOL_LIST(SYMBOL_DECLARATION)
 #undef SYMBOL_DECLARATION
 
+  // The special hidden symbol which is an empty string, but does not match
+  // any string when looked up in properties.
+  static String* hidden_symbol_;
+
   // GC callback function, called before and after mark-compact GC.
   // Allocations in the callback function are disallowed.
   static GCCallback global_gc_prologue_callback_;
diff --git a/src/objects-inl.h b/src/objects-inl.h
index 9aee342..941b84c 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -2438,10 +2438,15 @@
 
 
 uint32_t StringHasher::GetHash() {
+  // Get the calculated raw hash value and do some more bit ops to distribute
+  // the hash further. Ensure that we never return zero as the hash value.
   uint32_t result = raw_running_hash_;
   result += (result << 3);
   result ^= (result >> 11);
   result += (result << 15);
+  if (result == 0) {
+    result = 27;
+  }
   return result;
 }
 
diff --git a/src/objects.cc b/src/objects.cc
index b8228f0..44ebb3f 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -3113,8 +3113,12 @@
 
 
 int DescriptorArray::LinearSearch(String* name, int len) {
+  uint32_t hash = name->Hash();
   for (int number = 0; number < len; number++) {
-    if (name->Equals(GetKey(number)) && !is_null_descriptor(number)) {
+    String* entry = GetKey(number);
+    if ((entry->Hash() == hash) &&
+        name->Equals(entry) &&
+        !is_null_descriptor(number)) {
       return number;
     }
   }
@@ -4187,7 +4191,7 @@
 
 
 uint32_t String::ComputeAndSetHash() {
-  // Should only be call if hash code has not yet been computed.
+  // Should only be called if hash code has not yet been computed.
   ASSERT(!(length_field() & kHashComputedMask));
 
   // Compute the hash code.
@@ -4199,7 +4203,9 @@
 
   // Check the hash code is there.
   ASSERT(length_field() & kHashComputedMask);
-  return field >> kHashShift;
+  uint32_t result = field >> kHashShift;
+  ASSERT(result != 0);  // Ensure that the hash value of 0 is never computed.
+  return result;
 }
 
 
@@ -5081,6 +5087,45 @@
 }
 
 
+Object* JSObject::GetHiddenProperties(bool create_if_needed) {
+  String* key = Heap::hidden_symbol();
+  if (this->HasFastProperties()) {
+    // If the object has fast properties, check whether the first slot in the
+    // descriptor array matches the hidden symbol. Since the hidden symbols
+    // hash code is zero it will always occupy the first entry if present.
+    DescriptorArray* descriptors = this->map()->instance_descriptors();
+    if (descriptors->number_of_descriptors() > 0) {
+      if (descriptors->GetKey(0) == key) {
+#ifdef DEBUG
+        PropertyDetails details(descriptors->GetDetails(0));
+        ASSERT(details.type() == FIELD);
+#endif  // DEBUG
+        Object* value = descriptors->GetValue(0);
+        return FastPropertyAt(Descriptor::IndexFromValue(value));
+      }
+    }
+  }
+
+  // Only attempt to find the hidden properties in the local object and not
+  // in the prototype chain.
+  if (!this->HasLocalProperty(key)) {
+    // Hidden properties object not found. Allocate a new hidden properties
+    // object if requested. Otherwise return the undefined value.
+    if (create_if_needed) {
+      Object* obj = Heap::AllocateJSObject(
+          Top::context()->global_context()->object_function());
+      if (obj->IsFailure()) {
+        return obj;
+      }
+      return this->SetProperty(key, obj, DONT_ENUM);
+    } else {
+      return Heap::undefined_value();
+    }
+  }
+  return this->GetProperty(key);
+}
+
+
 bool JSObject::HasElementWithReceiver(JSObject* receiver, uint32_t index) {
   // Check access rights if needed.
   if (IsAccessCheckNeeded() &&
@@ -5927,13 +5972,20 @@
 // StringKey simply carries a string object as key.
 class StringKey : public HashTableKey {
  public:
-  explicit StringKey(String* string) : string_(string) { }
+  explicit StringKey(String* string) :
+      string_(string),
+      hash_(StringHash(string)) { }
 
   bool IsMatch(Object* string) {
+    // We know that all entries in a hash table had their hash keys created.
+    // Use that knowledge to have fast failure.
+    if (hash_ != StringHash(string)) {
+      return false;
+    }
     return string_->Equals(String::cast(string));
   }
 
-  uint32_t Hash() { return StringHash(string_); }
+  uint32_t Hash() { return hash_; }
 
   HashFunction GetHashFunction() { return StringHash; }
 
@@ -5946,6 +5998,7 @@
   bool IsStringKey() { return true; }
 
   String* string_;
+  uint32_t hash_;
 };
 
 
@@ -6072,7 +6125,9 @@
                                       static_cast<unsigned>(string_.length()));
     chars_ = buffer.Length();
     length_field_ = String::ComputeLengthAndHashField(&buffer, chars_);
-    return length_field_ >> String::kHashShift;
+    uint32_t result = length_field_ >> String::kHashShift;
+    ASSERT(result != 0);  // Ensure that the hash value of 0 is never computed.
+    return result;
   }
 
   Object* GetObject() {
diff --git a/src/objects.h b/src/objects.h
index 28df02a..c38aa38 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -1243,6 +1243,11 @@
   // Return the object's prototype (might be Heap::null_value()).
   inline Object* GetPrototype();
 
+  // Return the object's hidden properties object. If the object has no hidden
+  // properties and create_if_needed is true, then a new hidden property object
+  // will be allocated. Otherwise the Heap::undefined_value is returned.
+  Object* GetHiddenProperties(bool create_if_needed);
+
   // Tells whether the index'th element is present.
   inline bool HasElement(uint32_t index);
   bool HasElementWithReceiver(JSObject* receiver, uint32_t index);
diff --git a/src/spaces.h b/src/spaces.h
index 3d13219..8a3dc5b 100644
--- a/src/spaces.h
+++ b/src/spaces.h
@@ -1481,7 +1481,7 @@
   MapSpaceFreeList free_list_;
 
   // An array of page start address in a map space.
-  Address page_addresses_[kMaxMapPageIndex];
+  Address page_addresses_[kMaxMapPageIndex + 1];
 
  public:
   TRACK_MEMORY("MapSpace")
diff --git a/src/stub-cache.cc b/src/stub-cache.cc
index b7ef311..b472eab 100644
--- a/src/stub-cache.cc
+++ b/src/stub-cache.cc
@@ -656,9 +656,8 @@
 Object* LoadCallbackProperty(Arguments args) {
   Handle<JSObject> recv = args.at<JSObject>(0);
   AccessorInfo* callback = AccessorInfo::cast(args[1]);
-  v8::AccessorGetter fun =
-      FUNCTION_CAST<v8::AccessorGetter>(
-          v8::ToCData<Address>(callback->getter()));
+  Address getter_address = v8::ToCData<Address>(callback->getter());
+  v8::AccessorGetter fun = FUNCTION_CAST<v8::AccessorGetter>(getter_address);
   ASSERT(fun != NULL);
   Handle<String> name = args.at<String>(2);
   Handle<JSObject> holder = args.at<JSObject>(3);
@@ -669,10 +668,9 @@
   // locations of the arguments to this function maybe we don't have
   // to explicitly create the structure but can just pass a pointer
   // into the stack.
-  v8::AccessorInfo info(
-    v8::Utils::ToLocal(recv),
-    v8::Utils::ToLocal(data),
-    v8::Utils::ToLocal(holder));
+  v8::AccessorInfo info(v8::Utils::ToLocal(recv),
+                        v8::Utils::ToLocal(data),
+                        v8::Utils::ToLocal(holder));
   v8::Handle<v8::Value> result;
   {
     // Leaving JavaScript.
@@ -680,30 +678,25 @@
     result = fun(v8::Utils::ToLocal(name), info);
   }
   RETURN_IF_SCHEDULED_EXCEPTION();
-  if (result.IsEmpty()) {
-    return Heap::undefined_value();
-  } else {
-    return *v8::Utils::OpenHandle(*result);
-  }
+  if (result.IsEmpty()) return Heap::undefined_value();
+  return *v8::Utils::OpenHandle(*result);
 }
 
 
 Object* StoreCallbackProperty(Arguments args) {
   Handle<JSObject> recv = args.at<JSObject>(0);
   AccessorInfo* callback = AccessorInfo::cast(args[1]);
-  v8::AccessorSetter fun =
-      FUNCTION_CAST<v8::AccessorSetter>(
-          v8::ToCData<Address>(callback->setter()));
+  Address setter_address = v8::ToCData<Address>(callback->setter());
+  v8::AccessorSetter fun = FUNCTION_CAST<v8::AccessorSetter>(setter_address);
   ASSERT(fun != NULL);
   Handle<String> name = args.at<String>(2);
   Handle<Object> value = args.at<Object>(3);
   HandleScope scope;
   Handle<Object> data(callback->data());
   LOG(ApiNamedPropertyAccess("store", *recv, *name));
-  v8::AccessorInfo info(
-    v8::Utils::ToLocal(recv),
-    v8::Utils::ToLocal(data),
-    v8::Utils::ToLocal(recv));
+  v8::AccessorInfo info(v8::Utils::ToLocal(recv),
+                        v8::Utils::ToLocal(data),
+                        v8::Utils::ToLocal(recv));
   {
     // Leaving JavaScript.
     VMState state(OTHER);
@@ -715,28 +708,17 @@
 
 
 Object* LoadInterceptorProperty(Arguments args) {
-  HandleScope scope;
-  Handle<JSObject> recv = args.at<JSObject>(0);
-  Handle<JSObject> holder = args.at<JSObject>(1);
-  Handle<String> name = args.at<String>(2);
+  JSObject* recv = JSObject::cast(args[0]);
+  JSObject* holder = JSObject::cast(args[1]);
+  String* name = String::cast(args[2]);
   ASSERT(holder->HasNamedInterceptor());
   PropertyAttributes attr = NONE;
-  Handle<Object> result = GetPropertyWithInterceptor(recv, holder, name, &attr);
+  Object* result = holder->GetPropertyWithInterceptor(recv, name, &attr);
 
-  // GetPropertyWithInterceptor already converts a scheduled exception
-  // to a pending one if any. Don't use RETURN_IF_SCHEDULED_EXCEPTION() here.
-
-  // Make sure to propagate exceptions.
-  if (result.is_null())  {
-    // Failure::Exception is converted to a null handle in the
-    // handle-based methods such as SetProperty.  We therefore need
-    // to convert null handles back to exceptions.
-    ASSERT(Top::has_pending_exception());
-    return Failure::Exception();
-  }
+  if (result->IsFailure()) return result;
 
   // If the property is present, return it.
-  if (attr != ABSENT) return *result;
+  if (attr != ABSENT) return result;
 
   // If the top frame is an internal frame, this is really a call
   // IC. In this case, we simply return the undefined result which
@@ -744,43 +726,38 @@
   // function.
   StackFrameIterator it;
   it.Advance();  // skip exit frame
-  if (it.frame()->is_internal()) return *result;
+  if (it.frame()->is_internal()) return result;
 
   // If the load is non-contextual, just return the undefined result.
   // Note that both keyed and non-keyed loads may end up here, so we
   // can't use either LoadIC or KeyedLoadIC constructors.
   IC ic(IC::NO_EXTRA_FRAME);
   ASSERT(ic.target()->is_load_stub() || ic.target()->is_keyed_load_stub());
-  if (!ic.is_contextual()) return *result;
+  if (!ic.is_contextual()) return result;
 
   // Throw a reference error.
-  Handle<Object> error =
-      Factory::NewReferenceError("not_defined", HandleVector(&name, 1));
-  return Top::Throw(*error);
+  {
+    HandleScope scope;
+    // We cannot use the raw name pointer here since getting the
+    // property might cause a GC.  However, we can get the name from
+    // the stack using the arguments object.
+    Handle<String> name_handle = args.at<String>(2);
+    Handle<Object> error =
+        Factory::NewReferenceError("not_defined",
+                                   HandleVector(&name_handle, 1));
+    return Top::Throw(*error);
+  }
 }
 
 
 Object* StoreInterceptorProperty(Arguments args) {
-  HandleScope scope;
-  Handle<JSObject> recv = args.at<JSObject>(0);
-  Handle<String> name = args.at<String>(1);
-  Handle<Object> value = args.at<Object>(2);
+  JSObject* recv = JSObject::cast(args[0]);
+  String* name = String::cast(args[1]);
+  Object* value = args[2];
   ASSERT(recv->HasNamedInterceptor());
   PropertyAttributes attr = NONE;
-  Handle<Object> result = SetPropertyWithInterceptor(recv, name, value, attr);
-
-  // SetPropertyWithInterceptor already converts a scheduled exception
-  // to a pending one if any. Don't use RETURN_IF_SCHEDULED_EXCEPTION() here.
-
-  // Make sure to propagate exceptions.
-  if (result.is_null()) {
-    // Failure::Exception is converted to a null handle in the
-    // handle-based methods such as SetProperty.  We therefore need
-    // to convert null handles back to exceptions.
-    ASSERT(Top::has_pending_exception());
-    return Failure::Exception();
-  }
-  return *result;
+  Object* result = recv->SetPropertyWithInterceptor(name, value, attr);
+  return result;
 }