@@ -1941,8 +1941,7 @@ LInstruction* LChunkBuilder::DoStoreKeyedFastElement(
LOperand* key = needs_write_barrier
? UseTempRegister(instr->key())
: UseRegisterOrConstantAtStart(instr->key());

return AssignEnvironment(new LStoreKeyedFastElement(obj, key, val));
return new LStoreKeyedFastElement(obj, key, val);
}


@@ -4352,7 +4352,7 @@ MaybeObject* JSObject::DefineGetterSetter(String* name,
} else {
// Lookup the name.
LookupResult result(heap->isolate());
LocalLookup(name, &result);
LocalLookupRealNamedProperty(name, &result);
if (result.IsProperty()) {
// TODO(mstarzinger): We should check for result.IsDontDelete() here once
// we only call into the runtime once to set both getter and setter.
@@ -369,6 +369,10 @@ void StringSearch<PatternChar, SubjectChar>::PopulateBoyerMooreTable() {
shift_table[pattern_length] = 1;
suffix_table[pattern_length] = pattern_length + 1;

if (pattern_length <= start) {
return;
}

// Find suffixes.
PatternChar last_char = pattern[pattern_length - 1];
int suffix = pattern_length + 1;
@@ -34,8 +34,8 @@
// cannot be changed without changing the SCons build script.
#define MAJOR_VERSION 3
#define MINOR_VERSION 8
#define BUILD_NUMBER 2
#define PATCH_LEVEL 1
#define BUILD_NUMBER 3
#define PATCH_LEVEL 0
// Use 1 for candidates and 0 otherwise.
// (Boolean macro values are not supported by all preprocessors.)
#define IS_CANDIDATE_VERSION 0
@@ -3200,13 +3200,6 @@ void LCodeGen::DoStoreKeyedFastElement(LStoreKeyedFastElement* instr) {
Register elements = ToRegister(instr->object());
Register key = instr->key()->IsRegister() ? ToRegister(instr->key()) : no_reg;

// This instruction cannot handle the FAST_SMI_ONLY_ELEMENTS -> FAST_ELEMENTS
// conversion, so it deopts in that case.
if (instr->hydrogen()->ValueNeedsSmiCheck()) {
Condition cc = masm()->CheckSmi(value);
DeoptimizeIf(NegateCondition(cc), instr->environment());
}

// Do the store.
if (instr->key()->IsConstantOperand()) {
ASSERT(!instr->hydrogen()->NeedsWriteBarrier());
@@ -198,7 +198,7 @@ void LGapResolver::EmitMove(int index) {
if (cgen_->IsInteger32Constant(constant_source)) {
__ movl(dst, Immediate(cgen_->ToInteger32(constant_source)));
} else {
__ Move(dst, cgen_->ToHandle(constant_source));
__ LoadObject(dst, cgen_->ToHandle(constant_source));
}
} else {
ASSERT(destination->IsStackSlot());
@@ -207,7 +207,8 @@ void LGapResolver::EmitMove(int index) {
// Allow top 32 bits of an untagged Integer32 to be arbitrary.
__ movl(dst, Immediate(cgen_->ToInteger32(constant_source)));
} else {
__ Move(dst, cgen_->ToHandle(constant_source));
__ LoadObject(kScratchRegister, cgen_->ToHandle(constant_source));
__ movq(dst, kScratchRegister);
}
}

@@ -1929,8 +1929,7 @@ LInstruction* LChunkBuilder::DoStoreKeyedFastElement(
LOperand* key = needs_write_barrier
? UseTempRegister(instr->key())
: UseRegisterOrConstantAtStart(instr->key());

return AssignEnvironment(new LStoreKeyedFastElement(obj, key, val));
return new LStoreKeyedFastElement(obj, key, val);
}


@@ -789,6 +789,14 @@ class MacroAssembler: public Assembler {
void LoadHeapObject(Register result, Handle<HeapObject> object);
void PushHeapObject(Handle<HeapObject> object);

void LoadObject(Register result, Handle<Object> object) {
if (object->IsHeapObject()) {
LoadHeapObject(result, Handle<HeapObject>::cast(object));
} else {
Move(result, object);
}
}

// Load a global cell into a register.
void LoadGlobalCell(Register dst, Handle<JSGlobalPropertyCell> cell);

@@ -1422,6 +1422,40 @@ THREADED_TEST(EmptyInterceptorDoesNotAffectJSProperties) {
}

THREADED_TEST(SwitchFromInterceptorToAccessor) {
v8::HandleScope scope;
Handle<FunctionTemplate> templ = FunctionTemplate::New();
AddAccessor(templ, v8_str("age"),
SimpleAccessorGetter, SimpleAccessorSetter);
AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
LocalContext env;
env->Global()->Set(v8_str("Obj"), templ->GetFunction());
CompileRun("var obj = new Obj;"
"function setAge(i){ obj.age = i; };"
"for(var i = 0; i <= 10000; i++) setAge(i);");
// All i < 10000 go to the interceptor.
ExpectInt32("obj.interceptor_age", 9999);
// The last i goes to the accessor.
ExpectInt32("obj.accessor_age", 10000);
}

THREADED_TEST(SwitchFromAccessorToInterceptor) {
v8::HandleScope scope;
Handle<FunctionTemplate> templ = FunctionTemplate::New();
AddAccessor(templ, v8_str("age"),
SimpleAccessorGetter, SimpleAccessorSetter);
AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
LocalContext env;
env->Global()->Set(v8_str("Obj"), templ->GetFunction());
CompileRun("var obj = new Obj;"
"function setAge(i){ obj.age = i; };"
"for(var i = 20000; i >= 9999; i--) setAge(i);");
// All i >= 10000 go to the accessor.
ExpectInt32("obj.accessor_age", 10000);
// The last i goes to the interceptor.
ExpectInt32("obj.interceptor_age", 9999);
}

THREADED_TEST(SwitchFromInterceptorToAccessorWithInheritance) {
v8::HandleScope scope;
Handle<FunctionTemplate> parent = FunctionTemplate::New();
Handle<FunctionTemplate> child = FunctionTemplate::New();
@@ -1440,7 +1474,7 @@ THREADED_TEST(SwitchFromInterceptorToAccessor) {
ExpectInt32("child.accessor_age", 10000);
}

THREADED_TEST(SwitchFromAccessorToInterceptor) {
THREADED_TEST(SwitchFromAccessorToInterceptorWithInheritance) {
v8::HandleScope scope;
Handle<FunctionTemplate> parent = FunctionTemplate::New();
Handle<FunctionTemplate> child = FunctionTemplate::New();
@@ -1459,6 +1493,54 @@ THREADED_TEST(SwitchFromAccessorToInterceptor) {
ExpectInt32("child.interceptor_age", 9999);
}

THREADED_TEST(SwitchFromInterceptorToJSAccessor) {
v8::HandleScope scope;
Handle<FunctionTemplate> templ = FunctionTemplate::New();
AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
LocalContext env;
env->Global()->Set(v8_str("Obj"), templ->GetFunction());
CompileRun("var obj = new Obj;"
"function setter(i) { this.accessor_age = i; };"
"function getter() { return this.accessor_age; };"
"function setAge(i) { obj.age = i; };"
"Object.defineProperty(obj, 'age', { get:getter, set:setter });"
"for(var i = 0; i <= 10000; i++) setAge(i);");
// All i < 10000 go to the interceptor.
ExpectInt32("obj.interceptor_age", 9999);
// The last i goes to the JavaScript accessor.
ExpectInt32("obj.accessor_age", 10000);
// The installed JavaScript getter is still intact.
// This last part is a regression test for issue 1651 and relies on the fact
// that both interceptor and accessor are being installed on the same object.
ExpectInt32("obj.age", 10000);
ExpectBoolean("obj.hasOwnProperty('age')", true);
ExpectUndefined("Object.getOwnPropertyDescriptor(obj, 'age').value");
}

THREADED_TEST(SwitchFromJSAccessorToInterceptor) {
v8::HandleScope scope;
Handle<FunctionTemplate> templ = FunctionTemplate::New();
AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
LocalContext env;
env->Global()->Set(v8_str("Obj"), templ->GetFunction());
CompileRun("var obj = new Obj;"
"function setter(i) { this.accessor_age = i; };"
"function getter() { return this.accessor_age; };"
"function setAge(i) { obj.age = i; };"
"Object.defineProperty(obj, 'age', { get:getter, set:setter });"
"for(var i = 20000; i >= 9999; i--) setAge(i);");
// All i >= 10000 go to the accessor.
ExpectInt32("obj.accessor_age", 10000);
// The last i goes to the interceptor.
ExpectInt32("obj.interceptor_age", 9999);
// The installed JavaScript getter is still intact.
// This last part is a regression test for issue 1651 and relies on the fact
// that both interceptor and accessor are being installed on the same object.
ExpectInt32("obj.age", 10000);
ExpectBoolean("obj.hasOwnProperty('age')", true);
ExpectUndefined("Object.getOwnPropertyDescriptor(obj, 'age').value");
}

THREADED_TEST(SwitchFromInterceptorToProperty) {
v8::HandleScope scope;
Handle<FunctionTemplate> parent = FunctionTemplate::New();
@@ -0,0 +1,52 @@
// Copyright 2011 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.

// Flags: --allow-natives-syntax

// This test checks that young immediates embedded into code objects
// are referenced through a cell.

function f (k, a, b) {
// Create control flow for a.foo. Control flow resolution will
// be generated as a part of a gap move. Gap move operate on immediates as
// a.foo is a CONSTANT_FUNCTION.
var x = k ? a.foo : a.foo;
return x.prototype;
}

var a = { };

// Make sure that foo is a CONSTANT_FUNCTION but not be pretenured.
a.foo = (function () { return function () {}; })();

// Ensure that both branches of ternary operator have monomorphic type feedback.
f(true, a, a);
f(true, a, a);
f(false, a, a);
f(false, a, a);
%OptimizeFunctionOnNextCall(f);
f(true, a, a);