Remove ArrayPush from the custom call generators, and instead call directly to the handler in crankshaft.
R=mvstanton@chromium.org Review URL: https://codereview.chromium.org/137693003 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@18790 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
033174ab9b
commit
6b60546b16
@ -427,6 +427,21 @@ void CallDescriptors::InitializeForIsolate(Isolate* isolate) {
|
||||
descriptor->param_representations_ = representations;
|
||||
descriptor->platform_specific_descriptor_ = &noInlineDescriptor;
|
||||
}
|
||||
{
|
||||
CallInterfaceDescriptor* descriptor =
|
||||
isolate->call_descriptor(Isolate::CallHandler);
|
||||
static Register registers[] = { cp, // context
|
||||
r0, // receiver
|
||||
};
|
||||
static Representation representations[] = {
|
||||
Representation::Tagged(), // context
|
||||
Representation::Tagged(), // receiver
|
||||
};
|
||||
descriptor->register_param_count_ = 2;
|
||||
descriptor->register_params_ = registers;
|
||||
descriptor->param_representations_ = representations;
|
||||
descriptor->platform_specific_descriptor_ = &default_descriptor;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -7659,6 +7659,41 @@ bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall(
|
||||
Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
|
||||
return true;
|
||||
}
|
||||
case kArrayPush: {
|
||||
if (!expr->IsMonomorphic() || expr->check_type() != RECEIVER_MAP_CHECK) {
|
||||
return false;
|
||||
}
|
||||
if (receiver_map->instance_type() != JS_ARRAY_TYPE) return false;
|
||||
ElementsKind elements_kind = receiver_map->elements_kind();
|
||||
if (!IsFastElementsKind(elements_kind)) return false;
|
||||
AddCheckConstantFunction(expr->holder(), receiver, receiver_map);
|
||||
|
||||
HValue* op_vals[] = {
|
||||
context(),
|
||||
// Receiver.
|
||||
environment()->ExpressionStackAt(expr->arguments()->length())
|
||||
};
|
||||
|
||||
const int argc = expr->arguments()->length();
|
||||
// Includes receiver.
|
||||
PushArgumentsFromEnvironment(argc + 1);
|
||||
|
||||
CallInterfaceDescriptor* descriptor =
|
||||
isolate()->call_descriptor(Isolate::CallHandler);
|
||||
|
||||
ArrayPushStub stub(receiver_map->elements_kind(), argc);
|
||||
Handle<Code> code = stub.GetCode(isolate());
|
||||
HConstant* code_value = Add<HConstant>(code);
|
||||
|
||||
ASSERT((sizeof(op_vals) / kPointerSize) ==
|
||||
descriptor->environment_length());
|
||||
|
||||
HInstruction* call = New<HCallWithDescriptor>(
|
||||
code_value, argc + 1, descriptor,
|
||||
Vector<HValue*>(op_vals, descriptor->environment_length()));
|
||||
ast_context()->ReturnInstruction(call, expr->id());
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
// Not yet supported for inlining.
|
||||
break;
|
||||
|
@ -421,6 +421,20 @@ void CallDescriptors::InitializeForIsolate(Isolate* isolate) {
|
||||
descriptor->register_params_ = registers;
|
||||
descriptor->param_representations_ = representations;
|
||||
}
|
||||
{
|
||||
CallInterfaceDescriptor* descriptor =
|
||||
isolate->call_descriptor(Isolate::CallHandler);
|
||||
static Register registers[] = { esi, // context
|
||||
edx, // receiver
|
||||
};
|
||||
static Representation representations[] = {
|
||||
Representation::Tagged(), // context
|
||||
Representation::Tagged(), // receiver
|
||||
};
|
||||
descriptor->register_param_count_ = 2;
|
||||
descriptor->register_params_ = registers;
|
||||
descriptor->param_representations_ = representations;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -1076,6 +1076,7 @@ class Isolate {
|
||||
enum CallDescriptorKey {
|
||||
KeyedCall,
|
||||
NamedCall,
|
||||
CallHandler,
|
||||
ArgumentAdaptorCall,
|
||||
NUMBER_OF_CALL_DESCRIPTORS
|
||||
};
|
||||
|
@ -1282,41 +1282,6 @@ void CallStubCompiler::GenerateJumpFunction(Handle<Object> object,
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> CallStubCompiler::CompileArrayPushCall(
|
||||
Handle<Object> object,
|
||||
Handle<JSObject> holder,
|
||||
Handle<Cell> cell,
|
||||
Handle<JSFunction> function,
|
||||
Handle<String> name,
|
||||
Code::StubType type) {
|
||||
// If object is not an array or is observed or sealed, bail out to regular
|
||||
// call.
|
||||
if (!object->IsJSArray() ||
|
||||
!cell.is_null() ||
|
||||
Handle<JSArray>::cast(object)->map()->is_observed() ||
|
||||
!Handle<JSArray>::cast(object)->map()->is_extensible()) {
|
||||
return Handle<Code>::null();
|
||||
}
|
||||
|
||||
Label miss;
|
||||
|
||||
HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
|
||||
|
||||
Handle<Map> map(Handle<JSArray>::cast(object)->map());
|
||||
ElementsKind elements_kind = map->elements_kind();
|
||||
const int argc = arguments().immediate();
|
||||
|
||||
ArrayPushStub stub(elements_kind, argc);
|
||||
Handle<Code> code = stub.GetCode(isolate());
|
||||
StubCompiler::GenerateTailCall(masm(), code);
|
||||
|
||||
HandlerFrontendFooter(&miss);
|
||||
|
||||
// Return the generated code.
|
||||
return GetCode(type, name);
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> CallStubCompiler::CompileCallConstant(
|
||||
Handle<Object> object,
|
||||
Handle<JSObject> holder,
|
||||
@ -1913,13 +1878,6 @@ CallStubCompiler::CallStubCompiler(Isolate* isolate,
|
||||
|
||||
|
||||
bool CallStubCompiler::HasCustomCallGenerator(Handle<JSFunction> function) {
|
||||
if (function->shared()->HasBuiltinFunctionId()) {
|
||||
BuiltinFunctionId id = function->shared()->builtin_function_id();
|
||||
#define CALL_GENERATOR_CASE(name) if (id == k##name) return true;
|
||||
CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE)
|
||||
#undef CALL_GENERATOR_CASE
|
||||
}
|
||||
|
||||
CallOptimization optimization(function);
|
||||
return optimization.is_simple_api_call();
|
||||
}
|
||||
@ -1933,21 +1891,6 @@ Handle<Code> CallStubCompiler::CompileCustomCall(
|
||||
Handle<String> fname,
|
||||
Code::StubType type) {
|
||||
ASSERT(HasCustomCallGenerator(function));
|
||||
|
||||
if (function->shared()->HasBuiltinFunctionId()) {
|
||||
BuiltinFunctionId id = function->shared()->builtin_function_id();
|
||||
#define CALL_GENERATOR_CASE(name) \
|
||||
if (id == k##name) { \
|
||||
return CallStubCompiler::Compile##name##Call(object, \
|
||||
holder, \
|
||||
cell, \
|
||||
function, \
|
||||
fname, \
|
||||
type); \
|
||||
}
|
||||
CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE)
|
||||
#undef CALL_GENERATOR_CASE
|
||||
}
|
||||
CallOptimization optimization(function);
|
||||
ASSERT(optimization.is_simple_api_call());
|
||||
return CompileFastApiCall(optimization,
|
||||
|
@ -868,12 +868,6 @@ class KeyedStoreStubCompiler: public StoreStubCompiler {
|
||||
};
|
||||
|
||||
|
||||
// Subset of FUNCTIONS_WITH_ID_LIST with custom constant/global call
|
||||
// IC stubs.
|
||||
#define CUSTOM_CALL_IC_GENERATORS(V) \
|
||||
V(ArrayPush)
|
||||
|
||||
|
||||
class CallStubCompiler: public StubCompiler {
|
||||
public:
|
||||
CallStubCompiler(Isolate* isolate,
|
||||
@ -940,16 +934,6 @@ class CallStubCompiler: public StubCompiler {
|
||||
Handle<String> name,
|
||||
Code::StubType type);
|
||||
|
||||
#define DECLARE_CALL_GENERATOR(name) \
|
||||
Handle<Code> Compile##name##Call(Handle<Object> object, \
|
||||
Handle<JSObject> holder, \
|
||||
Handle<Cell> cell, \
|
||||
Handle<JSFunction> function, \
|
||||
Handle<String> fname, \
|
||||
Code::StubType type);
|
||||
CUSTOM_CALL_IC_GENERATORS(DECLARE_CALL_GENERATOR)
|
||||
#undef DECLARE_CALL_GENERATOR
|
||||
|
||||
Handle<Code> CompileFastApiCall(const CallOptimization& optimization,
|
||||
Handle<Object> object,
|
||||
Handle<JSObject> holder,
|
||||
|
@ -418,6 +418,20 @@ void CallDescriptors::InitializeForIsolate(Isolate* isolate) {
|
||||
descriptor->register_params_ = registers;
|
||||
descriptor->param_representations_ = representations;
|
||||
}
|
||||
{
|
||||
CallInterfaceDescriptor* descriptor =
|
||||
isolate->call_descriptor(Isolate::CallHandler);
|
||||
static Register registers[] = { rsi, // context
|
||||
rdx, // receiver
|
||||
};
|
||||
static Representation representations[] = {
|
||||
Representation::Tagged(), // context
|
||||
Representation::Tagged(), // receiver
|
||||
};
|
||||
descriptor->register_param_count_ = 2;
|
||||
descriptor->register_params_ = registers;
|
||||
descriptor->param_representations_ = representations;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -251,8 +251,7 @@ assertOptimized(shift_call);
|
||||
Object.seal(obj);
|
||||
assertThrows(function() { push_call(obj); }, TypeError);
|
||||
assertThrows(function() { shift_call(obj); }, TypeError);
|
||||
assertOptimized(push_call);
|
||||
// shift() doesn't have a custom call generator, so deopt will occur.
|
||||
assertUnoptimized(push_call);
|
||||
assertUnoptimized(shift_call);
|
||||
assertDoesNotThrow(function() { push_call(objControl); });
|
||||
assertDoesNotThrow(function() { shift_call(objControl); });
|
||||
|
Loading…
Reference in New Issue
Block a user