Commit 624b13a8 authored by vitalyr@chromium.org's avatar vitalyr@chromium.org

Custom call IC for String.fromCharCode.

Review URL: http://codereview.chromium.org/3291015

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@5433 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent d1a674f7
This diff is collapsed.
......@@ -1344,23 +1344,33 @@ bool Genesis::InstallNatives() {
}
static void InstallCustomCallGenerator(Handle<JSFunction> holder_function,
const char* function_name,
int id) {
Handle<JSObject> proto(JSObject::cast(holder_function->instance_prototype()));
static void InstallCustomCallGenerator(
Handle<JSFunction> holder_function,
CallStubCompiler::CustomGeneratorOwner owner_flag,
const char* function_name,
int id) {
Handle<JSObject> owner;
if (owner_flag == CallStubCompiler::FUNCTION) {
owner = Handle<JSObject>::cast(holder_function);
} else {
ASSERT(owner_flag == CallStubCompiler::INSTANCE_PROTOTYPE);
owner = Handle<JSObject>(
JSObject::cast(holder_function->instance_prototype()));
}
Handle<String> name = Factory::LookupAsciiSymbol(function_name);
Handle<JSFunction> function(JSFunction::cast(proto->GetProperty(*name)));
Handle<JSFunction> function(JSFunction::cast(owner->GetProperty(*name)));
function->shared()->set_function_data(Smi::FromInt(id));
}
void Genesis::InstallCustomCallGenerators() {
HandleScope scope;
#define INSTALL_CALL_GENERATOR(holder_fun, fun_name, name) \
#define INSTALL_CALL_GENERATOR(holder_fun, owner_flag, fun_name, name) \
{ \
Handle<JSFunction> holder(global_context()->holder_fun##_function()); \
const int id = CallStubCompiler::k##name##CallGenerator; \
InstallCustomCallGenerator(holder, #fun_name, id); \
InstallCustomCallGenerator(holder, CallStubCompiler::owner_flag, \
#fun_name, id); \
}
CUSTOM_CALL_IC_GENERATORS(INSTALL_CALL_GENERATOR)
#undef INSTALL_CALL_GENERATOR
......
......@@ -860,9 +860,14 @@ void Assembler::add(const Operand& dst, const Immediate& x) {
void Assembler::and_(Register dst, int32_t imm32) {
and_(dst, Immediate(imm32));
}
void Assembler::and_(Register dst, const Immediate& x) {
EnsureSpace ensure_space(this);
last_pc_ = pc_;
emit_arith(4, Operand(dst), Immediate(imm32));
emit_arith(4, Operand(dst), x);
}
......
......@@ -577,6 +577,7 @@ class Assembler : public Malloced {
void add(const Operand& dst, const Immediate& x);
void and_(Register dst, int32_t imm32);
void and_(Register dst, const Immediate& x);
void and_(Register dst, const Operand& src);
void and_(const Operand& src, Register dst);
void and_(const Operand& dst, const Immediate& x);
......
This diff is collapsed.
......@@ -1222,23 +1222,23 @@ CallStubCompiler::CallStubCompiler(int argc,
Object* CallStubCompiler::CompileCustomCall(int generator_id,
Object* object,
JSObject* holder,
JSGlobalPropertyCell* cell,
JSFunction* function,
String* fname,
CheckType check) {
ASSERT(generator_id >= 0 && generator_id < kNumCallGenerators);
switch (generator_id) {
#define CALL_GENERATOR_CASE(ignored1, ignored2, name) \
case k##name##CallGenerator: \
return CallStubCompiler::Compile##name##Call(object, \
holder, \
function, \
fname, \
check);
CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE)
String* fname) {
ASSERT(generator_id >= 0 && generator_id < kNumCallGenerators);
switch (generator_id) {
#define CALL_GENERATOR_CASE(ignored1, ignored2, ignored3, name) \
case k##name##CallGenerator: \
return CallStubCompiler::Compile##name##Call(object, \
holder, \
cell, \
function, \
fname);
CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE)
#undef CALL_GENERATOR_CASE
}
UNREACHABLE();
return Heap::undefined_value();
}
UNREACHABLE();
return Heap::undefined_value();
}
......
......@@ -612,21 +612,29 @@ class KeyedStoreStubCompiler: public StubCompiler {
// Installation of custom call generators for the selected builtins is
// handled by the bootstrapper.
//
// Each entry has a name of a global function (lowercased), a name of
// a builtin function on its instance prototype (the one the generator
// is set for), and a name of a generator itself (used to build ids
// and generator function names).
#define CUSTOM_CALL_IC_GENERATORS(V) \
V(array, push, ArrayPush) \
V(array, pop, ArrayPop) \
V(string, charCodeAt, StringCharCodeAt) \
V(string, charAt, StringCharAt)
// Each entry has a name of a global function (lowercased), a flag
// controlling whether the generator is set on the function itself or
// on its instance prototype, a name of a builtin function on the
// function or its instance prototype (the one the generator is set
// for), and a name of a generator itself (used to build ids and
// generator function names).
#define CUSTOM_CALL_IC_GENERATORS(V) \
V(array, INSTANCE_PROTOTYPE, push, ArrayPush) \
V(array, INSTANCE_PROTOTYPE, pop, ArrayPop) \
V(string, INSTANCE_PROTOTYPE, charCodeAt, StringCharCodeAt) \
V(string, INSTANCE_PROTOTYPE, charAt, StringCharAt) \
V(string, FUNCTION, fromCharCode, StringFromCharCode)
class CallStubCompiler: public StubCompiler {
public:
enum CustomGeneratorOwner {
FUNCTION,
INSTANCE_PROTOTYPE
};
enum {
#define DECLARE_CALL_GENERATOR_ID(ignored1, ignored2, name) \
#define DECLARE_CALL_GENERATOR_ID(ignored1, ignore2, ignored3, name) \
k##name##CallGenerator,
CUSTOM_CALL_IC_GENERATORS(DECLARE_CALL_GENERATOR_ID)
#undef DECLARE_CALL_GENERATOR_ID
......@@ -656,20 +664,21 @@ class CallStubCompiler: public StubCompiler {
JSFunction* function,
String* name);
// Compiles a custom call constant IC using the generator with given id.
// Compiles a custom call constant/global IC using the generator
// with given id. For constant calls cell is NULL.
Object* CompileCustomCall(int generator_id,
Object* object,
JSObject* holder,
JSGlobalPropertyCell* cell,
JSFunction* function,
String* name,
CheckType check);
String* name);
#define DECLARE_CALL_GENERATOR(ignored1, ignored2, name) \
Object* Compile##name##Call(Object* object, \
JSObject* holder, \
JSFunction* function, \
String* fname, \
CheckType check);
#define DECLARE_CALL_GENERATOR(ignored1, ignored2, ignored3, name) \
Object* Compile##name##Call(Object* object, \
JSObject* holder, \
JSGlobalPropertyCell* cell, \
JSFunction* function, \
String* fname);
CUSTOM_CALL_IC_GENERATORS(DECLARE_CALL_GENERATOR)
#undef DECLARE_CALL_GENERATOR
......@@ -689,6 +698,17 @@ class CallStubCompiler: public StubCompiler {
void GenerateNameCheck(String* name, Label* miss);
void GenerateGlobalReceiverCheck(JSObject* object,
JSObject* holder,
String* name,
Label* miss);
// Generates code to load the function from the cell checking that
// it still contains the same function.
void GenerateLoadFunctionFromCell(JSGlobalPropertyCell* cell,
JSFunction* function,
Label* miss);
// Generates a jump to CallIC miss stub. Returns Failure if the jump cannot
// be generated.
Object* GenerateMissBranch();
......
This diff is collapsed.
// Copyright 2010 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.
// Test String.fromCharCode.
// Test various receivers and arguments passed to String.fromCharCode.
Object.prototype.fromCharCode = function(x) { return this; };
var fcc = String.fromCharCode;
var fcc2 = fcc;
function constFun(x) { return function(y) { return x; }; }
function test(num) {
assertEquals(" ", String.fromCharCode(0x20));
assertEquals(" ", String.fromCharCode(0x20 + 0x10000));
assertEquals(" ", String.fromCharCode(0x20 - 0x10000));
assertEquals(" ", String.fromCharCode(0x20 + 0.5));
assertEquals("\u1234", String.fromCharCode(0x1234));
assertEquals("\u1234", String.fromCharCode(0x1234 + 0x10000));
assertEquals("\u1234", String.fromCharCode(0x1234 - 0x10000));
assertEquals("\u1234", String.fromCharCode(0x1234 + 0.5));
assertEquals(" ", String.fromCharCode(0x20, 0x20));
assertEquals(" ", String.fromCharCode(0x20 + 0.5, 0x20));
assertEquals(" ", fcc(0x20));
assertEquals(" ", fcc(0x20 + 0x10000));
assertEquals(" ", fcc(0x20 - 0x10000));
assertEquals(" ", fcc(0x20 + 0.5));
assertEquals("\u1234", fcc(0x1234));
assertEquals("\u1234", fcc(0x1234 + 0x10000));
assertEquals("\u1234", fcc(0x1234 - 0x10000));
assertEquals("\u1234", fcc(0x1234 + 0.5));
assertEquals(" ", fcc(0x20, 0x20));
assertEquals(" ", fcc(0x20 + 0.5, 0x20));
var receiver = (num < 5) ? String : (num < 9) ? "dummy" : 42;
fcc2 = (num < 5) ? fcc : (num < 9) ? constFun("dummy") : constFun(42);
var expected = (num < 5) ? " " : (num < 9) ? "dummy" : 42;
assertEquals(expected, receiver.fromCharCode(0x20));
assertEquals(expected, receiver.fromCharCode(0x20 - 0x10000));
assertEquals(expected, receiver.fromCharCode(0x20 + 0.5));
assertEquals(expected, fcc2(0x20));
assertEquals(expected, fcc2(0x20 - 0x10000));
assertEquals(expected, fcc2(0x20 + 0.5));
}
// Use loop to test the custom IC.
for (var i = 0; i < 10; i++) {
test(i);
}
// Test the custom IC works correctly when the map changes.
for (var i = 0; i < 10; i++) {
var expected = (i < 5) ? " " : 42;
if (i == 5) String.fromCharCode = function() { return 42; };
assertEquals(expected, String.fromCharCode(0x20));
}
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