Commit 93f2ed48 authored by verwaest@chromium.org's avatar verwaest@chromium.org

Handle all object types (minus smi) in load/store ICs

R=ulan@chromium.org

Review URL: https://chromiumcodereview.appspot.com/62953007

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@17755 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 883a5c80
......@@ -1298,34 +1298,33 @@ Register StubCompiler::CheckPrototypes(Handle<JSObject> object,
}
void LoadStubCompiler::HandlerFrontendFooter(Handle<Name> name,
Label* success,
Label* miss) {
void LoadStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) {
if (!miss->is_unused()) {
__ b(success);
Label success;
__ b(&success);
__ bind(miss);
TailCallBuiltin(masm(), MissBuiltin(kind()));
__ bind(&success);
}
}
void StoreStubCompiler::HandlerFrontendFooter(Handle<Name> name,
Label* success,
Label* miss) {
void StoreStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) {
if (!miss->is_unused()) {
__ b(success);
Label success;
__ b(&success);
GenerateRestoreName(masm(), miss, name);
TailCallBuiltin(masm(), MissBuiltin(kind()));
__ bind(&success);
}
}
Register LoadStubCompiler::CallbackHandlerFrontend(
Handle<JSObject> object,
Handle<Object> object,
Register object_reg,
Handle<JSObject> holder,
Handle<Name> name,
Label* success,
Handle<Object> callback) {
Label miss;
......@@ -1362,7 +1361,7 @@ Register LoadStubCompiler::CallbackHandlerFrontend(
__ b(ne, &miss);
}
HandlerFrontendFooter(name, success, &miss);
HandlerFrontendFooter(name, &miss);
return reg;
}
......@@ -1468,7 +1467,7 @@ void LoadStubCompiler::GenerateLoadCallback(
void LoadStubCompiler::GenerateLoadInterceptor(
Register holder_reg,
Handle<JSObject> object,
Handle<Object> object,
Handle<JSObject> interceptor_holder,
LookupResult* lookup,
Handle<Name> name) {
......@@ -2539,11 +2538,23 @@ Handle<Code> CallStubCompiler::CompileFastApiCall(
}
void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) {
Label success;
// Check that the object is a boolean.
__ LoadRoot(ip, Heap::kTrueValueRootIndex);
__ cmp(object, ip);
__ b(eq, &success);
__ LoadRoot(ip, Heap::kFalseValueRootIndex);
__ cmp(object, ip);
__ b(ne, miss);
__ bind(&success);
}
void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object,
Handle<JSObject> holder,
Handle<Name> name,
CheckType check,
Label* success) {
CheckType check) {
// ----------- S t a t e -------------
// -- r2 : name
// -- lr : return address
......@@ -2619,15 +2630,8 @@ void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object,
break;
}
case BOOLEAN_CHECK: {
Label fast;
// Check that the object is a boolean.
__ LoadRoot(ip, Heap::kTrueValueRootIndex);
__ cmp(r1, ip);
__ b(eq, &fast);
__ LoadRoot(ip, Heap::kFalseValueRootIndex);
__ cmp(r1, ip);
__ b(ne, &miss);
__ bind(&fast);
GenerateBooleanCheck(r1, &miss);
// Check that the maps starting from the prototype haven't changed.
GenerateDirectLoadGlobalFunctionPrototype(
masm(), Context::BOOLEAN_FUNCTION_INDEX, r0, &miss);
......@@ -2638,11 +2642,14 @@ void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object,
}
}
__ b(success);
Label success;
__ b(&success);
// Handle call cache miss.
__ bind(&miss);
GenerateMissBranch();
__ bind(&success);
}
......@@ -2671,10 +2678,7 @@ Handle<Code> CallStubCompiler::CompileCallConstant(
if (!code.is_null()) return code;
}
Label success;
CompileHandlerFrontend(object, holder, name, check, &success);
__ bind(&success);
CompileHandlerFrontend(object, holder, name, check);
CompileHandlerBackend(function);
// Return the generated code.
......@@ -2785,9 +2789,7 @@ Handle<Code> StoreStubCompiler::CompileStoreCallback(
Handle<JSObject> holder,
Handle<Name> name,
Handle<ExecutableAccessorInfo> callback) {
Label success;
HandlerFrontend(object, receiver(), holder, name, &success);
__ bind(&success);
HandlerFrontend(object, receiver(), holder, name);
// Stub never generated for non-global objects that require access checks.
ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded());
......@@ -2813,9 +2815,7 @@ Handle<Code> StoreStubCompiler::CompileStoreCallback(
Handle<JSObject> holder,
Handle<Name> name,
const CallOptimization& call_optimization) {
Label success;
HandlerFrontend(object, receiver(), holder, name, &success);
__ bind(&success);
HandlerFrontend(object, receiver(), holder, name);
Register values[] = { value() };
GenerateFastApiCall(
......@@ -2910,15 +2910,12 @@ Handle<Code> StoreStubCompiler::CompileStoreInterceptor(
Handle<Code> LoadStubCompiler::CompileLoadNonexistent(
Handle<JSObject> object,
Handle<Object> object,
Handle<JSObject> last,
Handle<Name> name,
Handle<JSGlobalObject> global) {
Label success;
NonexistentHandlerFrontend(object, last, name, &success, global);
NonexistentHandlerFrontend(object, last, name, global);
__ bind(&success);
// Return undefined if maps of the full prototype chain are still the
// same and no global property with this name contains a value.
__ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
......@@ -3013,12 +3010,12 @@ void LoadStubCompiler::GenerateLoadViaGetter(MacroAssembler* masm,
Handle<Code> LoadStubCompiler::CompileLoadGlobal(
Handle<JSObject> object,
Handle<Object> object,
Handle<GlobalObject> global,
Handle<PropertyCell> cell,
Handle<Name> name,
bool is_dont_delete) {
Label success, miss;
Label miss;
HandlerFrontendHeader(object, receiver(), global, name, &miss);
......@@ -3033,8 +3030,7 @@ Handle<Code> LoadStubCompiler::CompileLoadGlobal(
__ b(eq, &miss);
}
HandlerFrontendFooter(name, &success, &miss);
__ bind(&success);
HandlerFrontendFooter(name, &miss);
Counters* counters = isolate()->counters();
__ IncrementCounter(counters->named_load_global_stub(), 1, r1, r3);
......
......@@ -1267,34 +1267,33 @@ Register StubCompiler::CheckPrototypes(Handle<JSObject> object,
}
void LoadStubCompiler::HandlerFrontendFooter(Handle<Name> name,
Label* success,
Label* miss) {
void LoadStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) {
if (!miss->is_unused()) {
__ jmp(success);
Label success;
__ jmp(&success);
__ bind(miss);
TailCallBuiltin(masm(), MissBuiltin(kind()));
__ bind(&success);
}
}
void StoreStubCompiler::HandlerFrontendFooter(Handle<Name> name,
Label* success,
Label* miss) {
void StoreStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) {
if (!miss->is_unused()) {
__ jmp(success);
Label success;
__ jmp(&success);
GenerateRestoreName(masm(), miss, name);
TailCallBuiltin(masm(), MissBuiltin(kind()));
__ bind(&success);
}
}
Register LoadStubCompiler::CallbackHandlerFrontend(
Handle<JSObject> object,
Handle<Object> object,
Register object_reg,
Handle<JSObject> holder,
Handle<Name> name,
Label* success,
Handle<Object> callback) {
Label miss;
......@@ -1344,7 +1343,7 @@ Register LoadStubCompiler::CallbackHandlerFrontend(
__ j(not_equal, &miss);
}
HandlerFrontendFooter(name, success, &miss);
HandlerFrontendFooter(name, &miss);
return reg;
}
......@@ -1450,7 +1449,7 @@ void LoadStubCompiler::GenerateLoadConstant(Handle<Object> value) {
void LoadStubCompiler::GenerateLoadInterceptor(
Register holder_reg,
Handle<JSObject> object,
Handle<Object> object,
Handle<JSObject> interceptor_holder,
LookupResult* lookup,
Handle<Name> name) {
......@@ -2613,11 +2612,21 @@ Handle<Code> CallStubCompiler::CompileFastApiCall(
}
void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) {
Label success;
// Check that the object is a boolean.
__ cmp(object, factory()->true_value());
__ j(equal, &success);
__ cmp(object, factory()->false_value());
__ j(not_equal, miss);
__ bind(&success);
}
void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object,
Handle<JSObject> holder,
Handle<Name> name,
CheckType check,
Label* success) {
CheckType check) {
// ----------- S t a t e -------------
// -- ecx : name
// -- esp[0] : return address
......@@ -2696,13 +2705,7 @@ void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object,
break;
}
case BOOLEAN_CHECK: {
Label fast;
// Check that the object is a boolean.
__ cmp(edx, factory()->true_value());
__ j(equal, &fast);
__ cmp(edx, factory()->false_value());
__ j(not_equal, &miss);
__ bind(&fast);
GenerateBooleanCheck(edx, &miss);
// Check that the maps starting from the prototype haven't changed.
GenerateDirectLoadGlobalFunctionPrototype(
masm(), Context::BOOLEAN_FUNCTION_INDEX, eax, &miss);
......@@ -2713,11 +2716,14 @@ void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object,
}
}
__ jmp(success);
Label success;
__ jmp(&success);
// Handle call cache miss.
__ bind(&miss);
GenerateMissBranch();
__ bind(&success);
}
......@@ -2747,10 +2753,7 @@ Handle<Code> CallStubCompiler::CompileCallConstant(
if (!code.is_null()) return code;
}
Label success;
CompileHandlerFrontend(object, holder, name, check, &success);
__ bind(&success);
CompileHandlerFrontend(object, holder, name, check);
CompileHandlerBackend(function);
// Return the generated code.
......@@ -2885,9 +2888,7 @@ Handle<Code> StoreStubCompiler::CompileStoreCallback(
Handle<JSObject> holder,
Handle<Name> name,
Handle<ExecutableAccessorInfo> callback) {
Label success;
HandlerFrontend(object, receiver(), holder, name, &success);
__ bind(&success);
HandlerFrontend(object, receiver(), holder, name);
__ pop(scratch1()); // remove the return address
__ push(receiver());
......@@ -2911,9 +2912,7 @@ Handle<Code> StoreStubCompiler::CompileStoreCallback(
Handle<JSObject> holder,
Handle<Name> name,
const CallOptimization& call_optimization) {
Label success;
HandlerFrontend(object, receiver(), holder, name, &success);
__ bind(&success);
HandlerFrontend(object, receiver(), holder, name);
Register values[] = { value() };
GenerateFastApiCall(
......@@ -3020,15 +3019,12 @@ Handle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic(
Handle<Code> LoadStubCompiler::CompileLoadNonexistent(
Handle<JSObject> object,
Handle<Object> object,
Handle<JSObject> last,
Handle<Name> name,
Handle<JSGlobalObject> global) {
Label success;
NonexistentHandlerFrontend(object, last, name, &success, global);
NonexistentHandlerFrontend(object, last, name, global);
__ bind(&success);
// Return undefined if maps of the full prototype chain are still the
// same and no global property with this name contains a value.
__ mov(eax, isolate()->factory()->undefined_value());
......@@ -3118,12 +3114,12 @@ void LoadStubCompiler::GenerateLoadViaGetter(MacroAssembler* masm,
Handle<Code> LoadStubCompiler::CompileLoadGlobal(
Handle<JSObject> object,
Handle<Object> object,
Handle<GlobalObject> global,
Handle<PropertyCell> cell,
Handle<Name> name,
bool is_dont_delete) {
Label success, miss;
Label miss;
HandlerFrontendHeader(object, receiver(), global, name, &miss);
// Get the value from the cell.
......@@ -3143,8 +3139,7 @@ Handle<Code> LoadStubCompiler::CompileLoadGlobal(
__ Check(not_equal, kDontDeleteCellsCannotContainTheHole);
}
HandlerFrontendFooter(name, &success, &miss);
__ bind(&success);
HandlerFrontendFooter(name, &miss);
Counters* counters = isolate()->counters();
__ IncrementCounter(counters->named_load_global_stub(), 1);
......
......@@ -100,8 +100,7 @@ void IC::SetTargetAtAddress(Address address, Code* target) {
}
InlineCacheHolderFlag IC::GetCodeCacheForObject(Object* object,
JSObject* holder) {
InlineCacheHolderFlag IC::GetCodeCacheForObject(Object* object) {
if (object->IsJSObject()) return OWN_MAP;
// If the object is a value, we use the prototype map for the cache.
......@@ -111,13 +110,12 @@ InlineCacheHolderFlag IC::GetCodeCacheForObject(Object* object,
}
JSObject* IC::GetCodeCacheHolder(Isolate* isolate,
HeapObject* IC::GetCodeCacheHolder(Isolate* isolate,
Object* object,
InlineCacheHolderFlag holder) {
Object* map_owner =
holder == OWN_MAP ? object : object->GetPrototype(isolate);
ASSERT(map_owner->IsJSObject());
return JSObject::cast(map_owner);
return HeapObject::cast(map_owner);
}
......
This diff is collapsed.
......@@ -132,9 +132,11 @@ class IC {
// Determines which map must be used for keeping the code stub.
// These methods should not be called with undefined or null.
static inline InlineCacheHolderFlag GetCodeCacheForObject(Object* object,
JSObject* holder);
static inline JSObject* GetCodeCacheHolder(Isolate* isolate,
static inline InlineCacheHolderFlag GetCodeCacheForObject(Object* object);
// TODO(verwaest): This currently returns a HeapObject rather than JSObject*
// since loading the IC for loading the length from strings are stored on
// the string map directly, rather than on the JSObject-typed prototype.
static inline HeapObject* GetCodeCacheHolder(Isolate* isolate,
Object* object,
InlineCacheHolderFlag holder);
......@@ -180,13 +182,14 @@ class IC {
// Compute the handler either by compiling or by retrieving a cached version.
Handle<Code> ComputeHandler(LookupResult* lookup,
Handle<JSObject> receiver,
Handle<Object> object,
Handle<String> name,
Handle<Object> value = Handle<Code>::null());
virtual Handle<Code> CompileHandler(LookupResult* lookup,
Handle<JSObject> receiver,
Handle<Object> object,
Handle<String> name,
Handle<Object> value) {
Handle<Object> value,
InlineCacheHolderFlag cache_holder) {
UNREACHABLE();
return Handle<Code>::null();
}
......@@ -200,7 +203,7 @@ class IC {
void CopyICToMegamorphicCache(Handle<String> name);
bool IsTransitionedMapOfMonomorphicTarget(Map* receiver_map);
void PatchCache(Handle<HeapObject> receiver,
void PatchCache(Handle<Object> object,
Handle<String> name,
Handle<Code> code);
virtual void UpdateMegamorphicCache(Map* map, Name* name, Code* code);
......@@ -422,9 +425,10 @@ class LoadIC: public IC {
Handle<String> name);
virtual Handle<Code> CompileHandler(LookupResult* lookup,
Handle<JSObject> receiver,
Handle<Object> object,
Handle<String> name,
Handle<Object> unused);
Handle<Object> unused,
InlineCacheHolderFlag cache_holder);
private:
// Stub accessors.
......@@ -617,9 +621,10 @@ class StoreIC: public IC {
Handle<String> name,
Handle<Object> value);
virtual Handle<Code> CompileHandler(LookupResult* lookup,
Handle<JSObject> receiver,
Handle<Object> object,
Handle<String> name,
Handle<Object> value);
Handle<Object> value,
InlineCacheHolderFlag cache_holder);
private:
void set_target(Code* code) {
......
......@@ -4185,9 +4185,9 @@ Code::Flags Code::ComputeFlags(Kind kind,
Code::Flags Code::ComputeMonomorphicFlags(Kind kind,
ExtraICState extra_ic_state,
InlineCacheHolderFlag holder,
StubType type,
int argc,
InlineCacheHolderFlag holder) {
int argc) {
return ComputeFlags(kind, MONOMORPHIC, extra_ic_state, type, argc, holder);
}
......
......@@ -5253,9 +5253,9 @@ class Code: public HeapObject {
static inline Flags ComputeMonomorphicFlags(
Kind kind,
ExtraICState extra_ic_state = kNoExtraICState,
InlineCacheHolderFlag holder = OWN_MAP,
StubType type = NORMAL,
int argc = -1,
InlineCacheHolderFlag holder = OWN_MAP);
int argc = -1);
static inline InlineCacheState ExtractICStateFromFlags(Flags flags);
static inline StubType ExtractTypeFromFlags(Flags flags);
......
This diff is collapsed.
This diff is collapsed.
......@@ -298,11 +298,8 @@ void TypeFeedbackOracle::CallReceiverTypes(Call* expr,
Code::ExtraICState extra_ic_state =
CallIC::Contextual::encode(call_kind == CALL_AS_FUNCTION);
Code::Flags flags = Code::ComputeMonomorphicFlags(Code::CALL_IC,
extra_ic_state,
Code::NORMAL,
arity,
OWN_MAP);
Code::Flags flags = Code::ComputeMonomorphicFlags(
Code::CALL_IC, extra_ic_state, OWN_MAP, Code::NORMAL, arity);
CollectReceiverTypes(expr->CallFeedbackId(), name, flags, types);
}
......
......@@ -1200,34 +1200,33 @@ Register StubCompiler::CheckPrototypes(Handle<JSObject> object,
}
void LoadStubCompiler::HandlerFrontendFooter(Handle<Name> name,
Label* success,
Label* miss) {
void LoadStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) {
if (!miss->is_unused()) {
__ jmp(success);
Label success;
__ jmp(&success);
__ bind(miss);
TailCallBuiltin(masm(), MissBuiltin(kind()));
__ bind(&success);
}
}
void StoreStubCompiler::HandlerFrontendFooter(Handle<Name> name,
Label* success,
Label* miss) {
void StoreStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) {
if (!miss->is_unused()) {
__ jmp(success);
Label success;
__ jmp(&success);
GenerateRestoreName(masm(), miss, name);
TailCallBuiltin(masm(), MissBuiltin(kind()));
__ bind(&success);
}
}
Register LoadStubCompiler::CallbackHandlerFrontend(
Handle<JSObject> object,
Handle<Object> object,
Register object_reg,
Handle<JSObject> holder,
Handle<Name> name,
Label* success,
Handle<Object> callback) {
Label miss;
......@@ -1268,7 +1267,7 @@ Register LoadStubCompiler::CallbackHandlerFrontend(
__ j(not_equal, &miss);
}
HandlerFrontendFooter(name, success, &miss);
HandlerFrontendFooter(name, &miss);
return reg;
}
......@@ -1389,7 +1388,7 @@ void LoadStubCompiler::GenerateLoadConstant(Handle<Object> value) {
void LoadStubCompiler::GenerateLoadInterceptor(
Register holder_reg,
Handle<JSObject> object,
Handle<Object> object,
Handle<JSObject> interceptor_holder,
LookupResult* lookup,
Handle<Name> name) {
......@@ -2507,11 +2506,21 @@ Handle<Code> CallStubCompiler::CompileFastApiCall(
}
void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) {
Label success;
// Check that the object is a boolean.
__ CompareRoot(object, Heap::kTrueValueRootIndex);
__ j(equal, &success);
__ CompareRoot(object, Heap::kFalseValueRootIndex);
__ j(not_equal, miss);
__ bind(&success);
}
void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object,
Handle<JSObject> holder,
Handle<Name> name,
CheckType check,
Label* success) {
CheckType check) {
// ----------- S t a t e -------------
// rcx : function name
// rsp[0] : return address
......@@ -2593,13 +2602,7 @@ void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object,
break;
}
case BOOLEAN_CHECK: {
Label fast;
// Check that the object is a boolean.
__ CompareRoot(rdx, Heap::kTrueValueRootIndex);
__ j(equal, &fast);
__ CompareRoot(rdx, Heap::kFalseValueRootIndex);
__ j(not_equal, &miss);
__ bind(&fast);
GenerateBooleanCheck(rdx, &miss);
// Check that the maps starting from the prototype haven't changed.
GenerateDirectLoadGlobalFunctionPrototype(
masm(), Context::BOOLEAN_FUNCTION_INDEX, rax, &miss);
......@@ -2610,11 +2613,14 @@ void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object,
}
}
__ jmp(success);
Label success;
__ jmp(&success);
// Handle call cache miss.
__ bind(&miss);
GenerateMissBranch();
__ bind(&success);
}
......@@ -2643,10 +2649,7 @@ Handle<Code> CallStubCompiler::CompileCallConstant(
if (!code.is_null()) return code;
}
Label success;
CompileHandlerFrontend(object, holder, name, check, &success);
__ bind(&success);
CompileHandlerFrontend(object, holder, name, check);
CompileHandlerBackend(function);
// Return the generated code.
......@@ -2782,9 +2785,7 @@ Handle<Code> StoreStubCompiler::CompileStoreCallback(
Handle<JSObject> holder,
Handle<Name> name,
Handle<ExecutableAccessorInfo> callback) {
Label success;
HandlerFrontend(object, receiver(), holder, name, &success);
__ bind(&success);
HandlerFrontend(object, receiver(), holder, name);
__ PopReturnAddressTo(scratch1());
__ push(receiver());
......@@ -2808,9 +2809,7 @@ Handle<Code> StoreStubCompiler::CompileStoreCallback(
Handle<JSObject> holder,
Handle<Name> name,
const CallOptimization& call_optimization) {
Label success;
HandlerFrontend(object, receiver(), holder, name, &success);
__ bind(&success);
HandlerFrontend(object, receiver(), holder, name);
Register values[] = { value() };
GenerateFastApiCall(
......@@ -2924,15 +2923,12 @@ Handle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic(
Handle<Code> LoadStubCompiler::CompileLoadNonexistent(
Handle<JSObject> object,
Handle<Object> object,
Handle<JSObject> last,
Handle<Name> name,
Handle<JSGlobalObject> global) {
Label success;
NonexistentHandlerFrontend(object, last, name, &success, global);
NonexistentHandlerFrontend(object, last, name, global);
__ bind(&success);
// Return undefined if maps of the full prototype chain are still the
// same and no global property with this name contains a value.
__ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
......@@ -3027,12 +3023,12 @@ void LoadStubCompiler::GenerateLoadViaGetter(MacroAssembler* masm,
Handle<Code> LoadStubCompiler::CompileLoadGlobal(
Handle<JSObject> object,
Handle<Object> object,
Handle<GlobalObject> global,
Handle<PropertyCell> cell,
Handle<Name> name,
bool is_dont_delete) {
Label success, miss;
Label miss;
// TODO(verwaest): Directly store to rax. Currently we cannot do this, since
// rax is used as receiver(), which we would otherwise clobber before a
// potential miss.
......@@ -3051,8 +3047,7 @@ Handle<Code> LoadStubCompiler::CompileLoadGlobal(
__ Check(not_equal, kDontDeleteCellsCannotContainTheHole);
}
HandlerFrontendFooter(name, &success, &miss);
__ bind(&success);
HandlerFrontendFooter(name, &miss);
Counters* counters = isolate()->counters();
__ IncrementCounter(counters->named_load_global_stub(), 1);
......
// Copyright 2013 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.
Object.defineProperty(Boolean.prototype, "v",
{get:function() { return this; }});
function f(b) {
return b.v;
}
assertEquals("object", typeof f(true));
assertEquals("object", typeof f(true));
assertEquals("object", typeof f(true));
assertEquals("object", typeof f(true));
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment