// the inline_new flag so we only change the map if we generate a
// specialized construct stub.
ASSERT(in_object_properties <= Map::kMaxPreAllocatedPropertyFields);
- if (FLAG_inline_new &&
- fun->shared()->has_only_simple_this_property_assignments() &&
- fun->shared()->this_property_assignments_count() > 0) {
+ if (FLAG_inline_new
+ && fun->shared()->has_only_simple_this_property_assignments()
+ && fun->shared()->this_property_assignments_count() > 0
+ && !JSObject::cast(prototype)->HasSetter()) {
int count = fun->shared()->this_property_assignments_count();
if (count > in_object_properties) {
count = in_object_properties;
}
+static bool CallbacksObjectHasSetter(Object* callbacks) {
+ if (!callbacks->IsFixedArray()) {
+ ASSERT(callbacks->IsAccessorInfo() || callbacks->IsProxy());
+ return true;
+ } else {
+ Object* setter = (FixedArray::cast(callbacks))->get(kSetterIndex);
+ if (setter->IsJSFunction()) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+bool JSObject::HasSetter() {
+ for (Object* obj = this;
+ obj != Heap::null_value();
+ obj = JSObject::cast(obj)->GetPrototype()) {
+ JSObject* js_object = JSObject::cast(obj);
+ if (js_object->HasFastProperties()) {
+ DescriptorArray* descs = js_object->map()->instance_descriptors();
+ for (int i = 0; i < descs->number_of_descriptors(); i++) {
+ PropertyDetails details = descs->GetDetails(i);
+ if (details.type() == CALLBACKS) {
+ Object* callbacks = descs->GetCallbacksObject(i);
+ if (CallbacksObjectHasSetter(callbacks)) {
+ return true;
+ }
+ }
+ }
+ } else {
+ StringDictionary* dict = js_object->property_dictionary();
+ int capacity = dict->Capacity();
+ for (int i = 0; i < capacity; i++) {
+ Object* k = dict->KeyAt(i);
+ if (dict->IsKey(k)) {
+ PropertyType type = dict->DetailsAt(i).type();
+ ASSERT(type != FIELD);
+ if (type == CALLBACKS) {
+ Object* callbacks = dict->ValueAt(i);
+ if (CallbacksObjectHasSetter(callbacks)) {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+
+
Object* PixelArray::SetValue(uint32_t index, Object* value) {
uint8_t clamped_value = 0;
if (index < static_cast<uint32_t>(length())) {
Object* GetElementWithInterceptor(JSObject* receiver, uint32_t index);
+ bool HasSetter();
+
private:
Object* SetElementWithInterceptor(uint32_t index, Object* value);
Object* SetElementWithoutInterceptor(uint32_t index, Object* value);
}
-static Code* ComputeConstructStub(Handle<SharedFunctionInfo> shared) {
+static Code* ComputeConstructStub(Handle<JSFunction> function) {
if (FLAG_inline_new
- && shared->has_only_simple_this_property_assignments()) {
+ && function->shared()->has_only_simple_this_property_assignments()
+ && (!function->has_instance_prototype()
+ || !JSObject::cast(function->instance_prototype())->HasSetter())) {
ConstructStubCompiler compiler;
- Object* code = compiler.CompileConstructStub(*shared);
+ Object* code = compiler.CompileConstructStub(function->shared());
if (code->IsFailure()) {
return Builtins::builtin(Builtins::JSConstructStubGeneric);
}
return Code::cast(code);
}
- return shared->construct_stub();
+ return function->shared()->construct_stub();
}
bool first_allocation = !function->has_initial_map();
Handle<JSObject> result = Factory::NewJSObject(function);
if (first_allocation) {
- Handle<Map> map = Handle<Map>(function->initial_map());
Handle<Code> stub = Handle<Code>(
- ComputeConstructStub(Handle<SharedFunctionInfo>(function->shared())));
- function->shared()->set_construct_stub(*stub);
+ ComputeConstructStub(Handle<JSFunction>(function)));
+ shared->set_construct_stub(*stub);
}
Counters::constructed_objects.Increment();
--- /dev/null
+// Copyright 2008 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+function C1() {
+ this.x = 23;
+}
+C1.prototype = { set x(value) { this.y = 23; } }
+
+for (var i = 0; i < 10; i++) {
+ var c1 = new C1();
+ assertEquals("undefined", typeof c1.x);
+ assertEquals(23, c1.y);
+}
+
+
+function C2() {
+ this.x = 23;
+}
+C2.prototype = { }
+C2.prototype.__proto__ = { set x(value) { this.y = 23; } }
+
+for (var i = 0; i < 10; i++) {
+ var c2 = new C2();
+ assertEquals("undefined", typeof c2.x);
+ assertEquals(23, c2.y);
+}
+
+
+function C3() {
+ this.x = 23;
+}
+C3.prototype = { }
+C3.prototype.__defineSetter__('x', function(value) { this.y = 23; })
+
+for (var i = 0; i < 10; i++) {
+ var c3 = new C3();
+ assertEquals("undefined", typeof c3.x);
+ assertEquals(23, c3.y);
+}
+
+
+function C4() {
+ this.x = 23;
+}
+C4.prototype = { }
+C4.prototype.__proto__ = { }
+C4.prototype.__proto__.__defineSetter__('x', function(value) { this.y = 23; })
+
+for (var i = 0; i < 10; i++) {
+ var c4 = new C4();
+ assertEquals("undefined", typeof c4.x);
+ assertEquals(23, c4.y);
+}
+
+
+function D() {
+ this.x = 23;
+}
+D.prototype = 1;
+
+for (var i = 0; i < 10; i++) {
+ var d = new D();
+ assertEquals(23, d.x);
+ assertEquals("undefined", typeof d.y);
+}