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() { ...@@ -1344,23 +1344,33 @@ bool Genesis::InstallNatives() {
} }
static void InstallCustomCallGenerator(Handle<JSFunction> holder_function, static void InstallCustomCallGenerator(
const char* function_name, Handle<JSFunction> holder_function,
int id) { CallStubCompiler::CustomGeneratorOwner owner_flag,
Handle<JSObject> proto(JSObject::cast(holder_function->instance_prototype())); 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<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)); function->shared()->set_function_data(Smi::FromInt(id));
} }
void Genesis::InstallCustomCallGenerators() { void Genesis::InstallCustomCallGenerators() {
HandleScope scope; 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()); \ Handle<JSFunction> holder(global_context()->holder_fun##_function()); \
const int id = CallStubCompiler::k##name##CallGenerator; \ 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) CUSTOM_CALL_IC_GENERATORS(INSTALL_CALL_GENERATOR)
#undef INSTALL_CALL_GENERATOR #undef INSTALL_CALL_GENERATOR
......
...@@ -860,9 +860,14 @@ void Assembler::add(const Operand& dst, const Immediate& x) { ...@@ -860,9 +860,14 @@ void Assembler::add(const Operand& dst, const Immediate& x) {
void Assembler::and_(Register dst, int32_t imm32) { void Assembler::and_(Register dst, int32_t imm32) {
and_(dst, Immediate(imm32));
}
void Assembler::and_(Register dst, const Immediate& x) {
EnsureSpace ensure_space(this); EnsureSpace ensure_space(this);
last_pc_ = pc_; last_pc_ = pc_;
emit_arith(4, Operand(dst), Immediate(imm32)); emit_arith(4, Operand(dst), x);
} }
......
...@@ -577,6 +577,7 @@ class Assembler : public Malloced { ...@@ -577,6 +577,7 @@ class Assembler : public Malloced {
void add(const Operand& dst, const Immediate& x); void add(const Operand& dst, const Immediate& x);
void and_(Register dst, int32_t imm32); void and_(Register dst, int32_t imm32);
void and_(Register dst, const Immediate& x);
void and_(Register dst, const Operand& src); void and_(Register dst, const Operand& src);
void and_(const Operand& src, Register dst); void and_(const Operand& src, Register dst);
void and_(const Operand& dst, const Immediate& x); void and_(const Operand& dst, const Immediate& x);
......
This diff is collapsed.
...@@ -1222,23 +1222,23 @@ CallStubCompiler::CallStubCompiler(int argc, ...@@ -1222,23 +1222,23 @@ CallStubCompiler::CallStubCompiler(int argc,
Object* CallStubCompiler::CompileCustomCall(int generator_id, Object* CallStubCompiler::CompileCustomCall(int generator_id,
Object* object, Object* object,
JSObject* holder, JSObject* holder,
JSGlobalPropertyCell* cell,
JSFunction* function, JSFunction* function,
String* fname, String* fname) {
CheckType check) { ASSERT(generator_id >= 0 && generator_id < kNumCallGenerators);
ASSERT(generator_id >= 0 && generator_id < kNumCallGenerators); switch (generator_id) {
switch (generator_id) { #define CALL_GENERATOR_CASE(ignored1, ignored2, ignored3, name) \
#define CALL_GENERATOR_CASE(ignored1, ignored2, name) \ case k##name##CallGenerator: \
case k##name##CallGenerator: \ return CallStubCompiler::Compile##name##Call(object, \
return CallStubCompiler::Compile##name##Call(object, \ holder, \
holder, \ cell, \
function, \ function, \
fname, \ fname);
check); CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE)
CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE)
#undef CALL_GENERATOR_CASE #undef CALL_GENERATOR_CASE
} }
UNREACHABLE(); UNREACHABLE();
return Heap::undefined_value(); return Heap::undefined_value();
} }
......
...@@ -612,21 +612,29 @@ class KeyedStoreStubCompiler: public StubCompiler { ...@@ -612,21 +612,29 @@ class KeyedStoreStubCompiler: public StubCompiler {
// Installation of custom call generators for the selected builtins is // Installation of custom call generators for the selected builtins is
// handled by the bootstrapper. // handled by the bootstrapper.
// //
// Each entry has a name of a global function (lowercased), a name of // Each entry has a name of a global function (lowercased), a flag
// a builtin function on its instance prototype (the one the generator // controlling whether the generator is set on the function itself or
// is set for), and a name of a generator itself (used to build ids // on its instance prototype, a name of a builtin function on the
// and generator function names). // function or its instance prototype (the one the generator is set
#define CUSTOM_CALL_IC_GENERATORS(V) \ // for), and a name of a generator itself (used to build ids and
V(array, push, ArrayPush) \ // generator function names).
V(array, pop, ArrayPop) \ #define CUSTOM_CALL_IC_GENERATORS(V) \
V(string, charCodeAt, StringCharCodeAt) \ V(array, INSTANCE_PROTOTYPE, push, ArrayPush) \
V(string, charAt, StringCharAt) 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 { class CallStubCompiler: public StubCompiler {
public: public:
enum CustomGeneratorOwner {
FUNCTION,
INSTANCE_PROTOTYPE
};
enum { enum {
#define DECLARE_CALL_GENERATOR_ID(ignored1, ignored2, name) \ #define DECLARE_CALL_GENERATOR_ID(ignored1, ignore2, ignored3, name) \
k##name##CallGenerator, k##name##CallGenerator,
CUSTOM_CALL_IC_GENERATORS(DECLARE_CALL_GENERATOR_ID) CUSTOM_CALL_IC_GENERATORS(DECLARE_CALL_GENERATOR_ID)
#undef DECLARE_CALL_GENERATOR_ID #undef DECLARE_CALL_GENERATOR_ID
...@@ -656,20 +664,21 @@ class CallStubCompiler: public StubCompiler { ...@@ -656,20 +664,21 @@ class CallStubCompiler: public StubCompiler {
JSFunction* function, JSFunction* function,
String* name); 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* CompileCustomCall(int generator_id,
Object* object, Object* object,
JSObject* holder, JSObject* holder,
JSGlobalPropertyCell* cell,
JSFunction* function, JSFunction* function,
String* name, String* name);
CheckType check);
#define DECLARE_CALL_GENERATOR(ignored1, ignored2, name) \ #define DECLARE_CALL_GENERATOR(ignored1, ignored2, ignored3, name) \
Object* Compile##name##Call(Object* object, \ Object* Compile##name##Call(Object* object, \
JSObject* holder, \ JSObject* holder, \
JSFunction* function, \ JSGlobalPropertyCell* cell, \
String* fname, \ JSFunction* function, \
CheckType check); String* fname);
CUSTOM_CALL_IC_GENERATORS(DECLARE_CALL_GENERATOR) CUSTOM_CALL_IC_GENERATORS(DECLARE_CALL_GENERATOR)
#undef DECLARE_CALL_GENERATOR #undef DECLARE_CALL_GENERATOR
...@@ -689,6 +698,17 @@ class CallStubCompiler: public StubCompiler { ...@@ -689,6 +698,17 @@ class CallStubCompiler: public StubCompiler {
void GenerateNameCheck(String* name, Label* miss); 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 // Generates a jump to CallIC miss stub. Returns Failure if the jump cannot
// be generated. // be generated.
Object* GenerateMissBranch(); 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