void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
- InlineFunctionGenerator generator = FindInlineFunctionGenerator(expr);
- if (generator != nullptr) {
- Comment cmnt(masm_, "[ InlineRuntimeCall");
- EmitInlineRuntimeCall(expr, generator);
- return;
- }
-
- Comment cmnt(masm_, "[ CallRuntime");
ZoneList<Expression*>* args = expr->arguments();
int arg_count = args->length();
if (expr->is_jsruntime()) {
+ Comment cmnt(masm_, "[ CallRuntime");
// Push the builtins object as the receiver.
Register receiver = LoadDescriptor::ReceiverRegister();
__ ldr(receiver, GlobalObjectOperand());
__ str(r0, MemOperand(sp, kPointerSize));
// Push the arguments ("left-to-right").
- int arg_count = args->length();
for (int i = 0; i < arg_count; i++) {
VisitForStackValue(args->at(i));
}
__ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
context()->DropAndPlug(1, r0);
+
} else {
- // Push the arguments ("left-to-right").
- for (int i = 0; i < arg_count; i++) {
- VisitForStackValue(args->at(i));
- }
+ const Runtime::Function* function = expr->function();
+ switch (function->function_id) {
+#define CALL_INTRINSIC_GENERATOR(Name) \
+ case Runtime::kInline##Name: { \
+ Comment cmnt(masm_, "[ Inline" #Name); \
+ return Emit##Name(expr); \
+ }
+ FOR_EACH_FULL_CODE_INTRINSIC(CALL_INTRINSIC_GENERATOR)
+#undef CALL_INTRINSIC_GENERATOR
+ default: {
+ Comment cmnt(masm_, "[ CallRuntime for unhandled intrinsic");
+ // Push the arguments ("left-to-right").
+ for (int i = 0; i < arg_count; i++) {
+ VisitForStackValue(args->at(i));
+ }
- // Call the C runtime function.
- __ CallRuntime(expr->function(), arg_count);
- context()->Plug(r0);
+ // Call the C runtime function.
+ __ CallRuntime(expr->function(), arg_count);
+ context()->Plug(r0);
+ }
+ }
}
}
void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
- InlineFunctionGenerator generator = FindInlineFunctionGenerator(expr);
- if (generator != nullptr) {
- Comment cmnt(masm_, "[ InlineRuntimeCall");
- EmitInlineRuntimeCall(expr, generator);
- return;
- }
-
- Comment cmnt(masm_, "[ CallRunTime");
ZoneList<Expression*>* args = expr->arguments();
int arg_count = args->length();
if (expr->is_jsruntime()) {
+ Comment cmnt(masm_, "[ CallRunTime");
// Push the builtins object as the receiver.
__ Ldr(x10, GlobalObjectMemOperand());
__ Ldr(LoadDescriptor::ReceiverRegister(),
__ Pop(x10);
__ Push(x0, x10);
- int arg_count = args->length();
for (int i = 0; i < arg_count; i++) {
VisitForStackValue(args->at(i));
}
__ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
context()->DropAndPlug(1, x0);
+
} else {
- // Push the arguments ("left-to-right").
- for (int i = 0; i < arg_count; i++) {
- VisitForStackValue(args->at(i));
- }
+ const Runtime::Function* function = expr->function();
+ switch (function->function_id) {
+#define CALL_INTRINSIC_GENERATOR(Name) \
+ case Runtime::kInline##Name: { \
+ Comment cmnt(masm_, "[ Inline" #Name); \
+ return Emit##Name(expr); \
+ }
+ FOR_EACH_FULL_CODE_INTRINSIC(CALL_INTRINSIC_GENERATOR)
+#undef CALL_INTRINSIC_GENERATOR
+ default: {
+ Comment cmnt(masm_, "[ CallRuntime for unhandled intrinsic");
+ // Push the arguments ("left-to-right").
+ for (int i = 0; i < arg_count; i++) {
+ VisitForStackValue(args->at(i));
+ }
- // Call the C runtime function.
- __ CallRuntime(expr->function(), arg_count);
- context()->Plug(x0);
+ // Call the C runtime function.
+ __ CallRuntime(expr->function(), arg_count);
+ context()->Plug(x0);
+ }
+ }
}
}
}
-// Lookup table for code generators for special runtime calls which are
-// generated inline.
-#define INLINE_FUNCTION_GENERATOR_ADDRESS(Name, argc, ressize) \
- &FullCodeGenerator::Emit##Name,
-
-const FullCodeGenerator::InlineFunctionGenerator
- FullCodeGenerator::kInlineFunctionGenerators[] = {
- INLINE_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS)
- };
-#undef INLINE_FUNCTION_GENERATOR_ADDRESS
-
-
-FullCodeGenerator::InlineFunctionGenerator
-FullCodeGenerator::FindInlineFunctionGenerator(CallRuntime* expr) {
- const Runtime::Function* function = expr->function();
- if (function == nullptr || function->intrinsic_type != Runtime::INLINE) {
- return nullptr;
- }
- Runtime::FunctionId id = function->function_id;
- if (id < Runtime::kFirstInlineFunction || Runtime::kLastInlineFunction < id) {
- return nullptr;
- }
- return kInlineFunctionGenerators[static_cast<int>(id) -
- static_cast<int>(
- Runtime::kFirstInlineFunction)];
-}
-
-
-void FullCodeGenerator::EmitInlineRuntimeCall(
- CallRuntime* expr, InlineFunctionGenerator generator) {
- ((*this).*(generator))(expr);
-}
-
-
void FullCodeGenerator::EmitGeneratorNext(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
DCHECK(args->length() == 2);
}
};
- // Type of a member function that generates inline code for a native function.
- typedef void (FullCodeGenerator::*InlineFunctionGenerator)(CallRuntime* expr);
-
- static const InlineFunctionGenerator kInlineFunctionGenerators[];
-
// A platform-specific utility to overwrite the accumulator register
// with a GC-safe value.
void ClearAccumulator();
void EmitKeyedCallWithLoadIC(Call* expr, Expression* key);
void EmitKeyedSuperCallWithLoadIC(Call* expr);
- // Platform-specific code for inline runtime calls.
- InlineFunctionGenerator FindInlineFunctionGenerator(CallRuntime* expr);
-
- void EmitInlineRuntimeCall(CallRuntime* expr,
- InlineFunctionGenerator generator);
-
-#define EMIT_INLINE_RUNTIME_CALL(name, x, y) \
- void Emit##name(CallRuntime* expr);
- INLINE_FUNCTION_LIST(EMIT_INLINE_RUNTIME_CALL)
-#undef EMIT_INLINE_RUNTIME_CALL
+#define FOR_EACH_FULL_CODE_INTRINSIC(F) \
+ F(IsSmi) \
+ F(IsNonNegativeSmi) \
+ F(IsArray) \
+ F(IsRegExp) \
+ F(IsJSProxy) \
+ F(IsConstructCall) \
+ F(CallFunction) \
+ F(DefaultConstructorCallSuper) \
+ F(ArgumentsLength) \
+ F(Arguments) \
+ F(ValueOf) \
+ F(SetValueOf) \
+ F(DateField) \
+ F(StringCharFromCode) \
+ F(StringCharAt) \
+ F(OneByteSeqStringSetChar) \
+ F(TwoByteSeqStringSetChar) \
+ F(ObjectEquals) \
+ F(IsObject) \
+ F(IsFunction) \
+ F(IsUndetectableObject) \
+ F(IsSpecObject) \
+ F(IsStringWrapperSafeForDefaultValueOf) \
+ F(MathPow) \
+ F(IsMinusZero) \
+ F(HasCachedArrayIndex) \
+ F(GetCachedArrayIndex) \
+ F(FastOneByteArrayJoin) \
+ F(GeneratorNext) \
+ F(GeneratorThrow) \
+ F(DebugBreakInOptimizedCode) \
+ F(ClassOf) \
+ F(StringCharCodeAt) \
+ F(StringAdd) \
+ F(SubString) \
+ F(StringCompare) \
+ F(RegExpExec) \
+ F(RegExpConstructResult) \
+ F(GetFromCache) \
+ F(NumberToString) \
+ F(DebugIsActive)
+
+#define GENERATOR_DECLARATION(Name) void Emit##Name(CallRuntime* call);
+ FOR_EACH_FULL_CODE_INTRINSIC(GENERATOR_DECLARATION)
+#undef GENERATOR_DECLARATION
// Platform-specific code for resuming generators.
void EmitGeneratorResume(Expression *generator,
void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
- InlineFunctionGenerator generator = FindInlineFunctionGenerator(expr);
- if (generator != nullptr) {
- Comment cmnt(masm_, "[ InlineRuntimeCall");
- EmitInlineRuntimeCall(expr, generator);
- return;
- }
-
- Comment cmnt(masm_, "[ CallRuntime");
ZoneList<Expression*>* args = expr->arguments();
+ int arg_count = args->length();
if (expr->is_jsruntime()) {
+ Comment cmnt(masm_, "[ CallRuntime");
// Push the builtins object as receiver.
__ mov(eax, GlobalObjectOperand());
__ push(FieldOperand(eax, GlobalObject::kBuiltinsOffset));
__ push(Operand(esp, 0));
__ mov(Operand(esp, kPointerSize), eax);
- // Code common for calls using the IC.
- ZoneList<Expression*>* args = expr->arguments();
- int arg_count = args->length();
+ // Push the arguments ("left-to-right").
for (int i = 0; i < arg_count; i++) {
VisitForStackValue(args->at(i));
}
CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS);
__ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize));
__ CallStub(&stub);
+
// Restore context register.
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
context()->DropAndPlug(1, eax);
} else {
- // Push the arguments ("left-to-right").
- int arg_count = args->length();
- for (int i = 0; i < arg_count; i++) {
- VisitForStackValue(args->at(i));
- }
-
- // Call the C runtime function.
- __ CallRuntime(expr->function(), arg_count);
+ const Runtime::Function* function = expr->function();
+ switch (function->function_id) {
+#define CALL_INTRINSIC_GENERATOR(Name) \
+ case Runtime::kInline##Name: { \
+ Comment cmnt(masm_, "[ Inline" #Name); \
+ return Emit##Name(expr); \
+ }
+ FOR_EACH_FULL_CODE_INTRINSIC(CALL_INTRINSIC_GENERATOR)
+#undef CALL_INTRINSIC_GENERATOR
+ default: {
+ Comment cmnt(masm_, "[ CallRuntime for unhandled intrinsic");
+ // Push the arguments ("left-to-right").
+ for (int i = 0; i < arg_count; i++) {
+ VisitForStackValue(args->at(i));
+ }
- context()->Plug(eax);
+ // Call the C runtime function.
+ __ CallRuntime(expr->function(), arg_count);
+ context()->Plug(eax);
+ }
+ }
}
}
void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
- InlineFunctionGenerator generator = FindInlineFunctionGenerator(expr);
- if (generator != nullptr) {
- Comment cmnt(masm_, "[ InlineRuntimeCall");
- EmitInlineRuntimeCall(expr, generator);
- return;
- }
-
- Comment cmnt(masm_, "[ CallRuntime");
ZoneList<Expression*>* args = expr->arguments();
int arg_count = args->length();
if (expr->is_jsruntime()) {
+ Comment cmnt(masm_, "[ CallRuntime");
// Push the builtins object as the receiver.
Register receiver = LoadDescriptor::ReceiverRegister();
__ lw(receiver, GlobalObjectOperand());
__ sw(v0, MemOperand(sp, kPointerSize));
// Push the arguments ("left-to-right").
- int arg_count = args->length();
for (int i = 0; i < arg_count; i++) {
VisitForStackValue(args->at(i));
}
__ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
context()->DropAndPlug(1, v0);
+
} else {
- // Push the arguments ("left-to-right").
- for (int i = 0; i < arg_count; i++) {
- VisitForStackValue(args->at(i));
- }
+ const Runtime::Function* function = expr->function();
+ switch (function->function_id) {
+#define CALL_INTRINSIC_GENERATOR(Name) \
+ case Runtime::kInline##Name: { \
+ Comment cmnt(masm_, "[ Inline" #Name); \
+ return Emit##Name(expr); \
+ }
+ FOR_EACH_FULL_CODE_INTRINSIC(CALL_INTRINSIC_GENERATOR)
+#undef CALL_INTRINSIC_GENERATOR
+ default: {
+ Comment cmnt(masm_, "[ CallRuntime for unhandled intrinsic");
+ // Push the arguments ("left-to-right").
+ for (int i = 0; i < arg_count; i++) {
+ VisitForStackValue(args->at(i));
+ }
- // Call the C runtime function.
- __ CallRuntime(expr->function(), arg_count);
- context()->Plug(v0);
+ // Call the C runtime function.
+ __ CallRuntime(expr->function(), arg_count);
+ context()->Plug(v0);
+ }
+ }
}
}
void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
- InlineFunctionGenerator generator = FindInlineFunctionGenerator(expr);
- if (generator != nullptr) {
- Comment cmnt(masm_, "[ InlineRuntimeCall");
- EmitInlineRuntimeCall(expr, generator);
- return;
- }
-
- Comment cmnt(masm_, "[ CallRuntime");
ZoneList<Expression*>* args = expr->arguments();
int arg_count = args->length();
if (expr->is_jsruntime()) {
+ Comment cmnt(masm_, "[ CallRuntime");
// Push the builtins object as the receiver.
Register receiver = LoadDescriptor::ReceiverRegister();
__ ld(receiver, GlobalObjectOperand());
__ sd(v0, MemOperand(sp, kPointerSize));
// Push the arguments ("left-to-right").
- int arg_count = args->length();
for (int i = 0; i < arg_count; i++) {
VisitForStackValue(args->at(i));
}
context()->DropAndPlug(1, v0);
} else {
- // Push the arguments ("left-to-right").
- for (int i = 0; i < arg_count; i++) {
- VisitForStackValue(args->at(i));
- }
+ const Runtime::Function* function = expr->function();
+ switch (function->function_id) {
+#define CALL_INTRINSIC_GENERATOR(Name) \
+ case Runtime::kInline##Name: { \
+ Comment cmnt(masm_, "[ Inline" #Name); \
+ return Emit##Name(expr); \
+ }
+ FOR_EACH_FULL_CODE_INTRINSIC(CALL_INTRINSIC_GENERATOR)
+#undef CALL_INTRINSIC_GENERATOR
+ default: {
+ Comment cmnt(masm_, "[ CallRuntime for unhandled intrinsic");
+ // Push the arguments ("left-to-right").
+ for (int i = 0; i < arg_count; i++) {
+ VisitForStackValue(args->at(i));
+ }
- // Call the C runtime function.
- __ CallRuntime(expr->function(), arg_count);
- context()->Plug(v0);
+ // Call the C runtime function.
+ __ CallRuntime(expr->function(), arg_count);
+ context()->Plug(v0);
+ }
+ }
}
}
void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
- InlineFunctionGenerator generator = FindInlineFunctionGenerator(expr);
- if (generator != nullptr) {
- Comment cmnt(masm_, "[ InlineRuntimeCall");
- EmitInlineRuntimeCall(expr, generator);
- return;
- }
-
- Comment cmnt(masm_, "[ CallRuntime");
ZoneList<Expression*>* args = expr->arguments();
int arg_count = args->length();
if (expr->is_jsruntime()) {
+ Comment cmnt(masm_, "[ CallRuntime");
// Push the builtins object as the receiver.
Register receiver = LoadDescriptor::ReceiverRegister();
__ LoadP(receiver, GlobalObjectOperand());
__ StoreP(r3, MemOperand(sp, kPointerSize));
// Push the arguments ("left-to-right").
- int arg_count = args->length();
for (int i = 0; i < arg_count; i++) {
VisitForStackValue(args->at(i));
}
__ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
context()->DropAndPlug(1, r3);
+
} else {
- // Push the arguments ("left-to-right").
- for (int i = 0; i < arg_count; i++) {
- VisitForStackValue(args->at(i));
- }
+ const Runtime::Function* function = expr->function();
+ switch (function->function_id) {
+#define CALL_INTRINSIC_GENERATOR(Name) \
+ case Runtime::kInline##Name: { \
+ Comment cmnt(masm_, "[ Inline" #Name); \
+ return Emit##Name(expr); \
+ }
+ FOR_EACH_FULL_CODE_INTRINSIC(CALL_INTRINSIC_GENERATOR)
+#undef CALL_INTRINSIC_GENERATOR
+ default: {
+ Comment cmnt(masm_, "[ CallRuntime for unhandled intrinsic");
+ // Push the arguments ("left-to-right").
+ for (int i = 0; i < arg_count; i++) {
+ VisitForStackValue(args->at(i));
+ }
- // Call the C runtime function.
- __ CallRuntime(expr->function(), arg_count);
- context()->Plug(r3);
+ // Call the C runtime function.
+ __ CallRuntime(expr->function(), arg_count);
+ context()->Plug(r3);
+ }
+ }
}
}
static const Runtime::Function kIntrinsicFunctions[] = {
- RUNTIME_FUNCTION_LIST(F) INLINE_FUNCTION_LIST(F)
- INLINE_OPTIMIZED_FUNCTION_LIST(F) RUNTIME_FUNCTION_LIST(I)
- INLINE_FUNCTION_LIST(I) INLINE_OPTIMIZED_FUNCTION_LIST(I)};
+ FOR_EACH_INTRINSIC(F) FOR_EACH_INTRINSIC(I)};
#undef I
#undef F
// The interface to C++ runtime functions.
// ----------------------------------------------------------------------------
-// RUNTIME_FUNCTION_LIST_ALWAYS defines runtime calls available in both
-// release and debug mode.
-// This macro should only be used by the macro RUNTIME_FUNCTION_LIST.
-
// WARNING: RUNTIME_FUNCTION_LIST_ALWAYS_* is a very large macro that caused
// MSVC Intellisense to crash. It was broken into two macros to work around
// this problem. Please avoid large recursive macros whenever possible.
#endif
-// ----------------------------------------------------------------------------
-// RUNTIME_FUNCTION_LIST defines all runtime functions accessed
-// either directly by id (via the code generator), or indirectly
-// via a native call by name (from within JS code).
-// Entries have the form F(name, number of arguments, number of return values).
-
#define RUNTIME_FUNCTION_LIST_RETURN_OBJECT(F) \
RUNTIME_FUNCTION_LIST_ALWAYS_1(F) \
RUNTIME_FUNCTION_LIST_ALWAYS_2(F) \
RUNTIME_FUNCTION_LIST_I18N_SUPPORT(F)
+// RUNTIME_FUNCTION_LIST_ defines the intrinsics typically implemented only
+// as runtime functions. These come in 2 flavors, either returning an object or
+// returning a pair.
+// Entries have the form F(name, number of arguments, number of return values).
#define RUNTIME_FUNCTION_LIST(F) \
RUNTIME_FUNCTION_LIST_RETURN_OBJECT(F) \
RUNTIME_FUNCTION_LIST_RETURN_PAIR(F)
+
// ----------------------------------------------------------------------------
-// INLINE_FUNCTION_LIST defines all inlined functions accessed
-// with a native call of the form %_name from within JS code.
+// INLINE_FUNCTION_LIST defines the intrinsics typically handled specially by
+// the various compilers.
// Entries have the form F(name, number of arguments, number of return values).
#define INLINE_FUNCTION_LIST(F) \
F(IsSmi, 1, 1) \
// ----------------------------------------------------------------------------
-// INLINE_OPTIMIZED_FUNCTION_LIST defines all inlined functions accessed
-// with a native call of the form %_name from within JS code that also have
-// a corresponding runtime function, that is called from non-optimized code.
-// For the benefit of (fuzz) tests, the runtime version can also be called
-// directly as %name (i.e. without the leading underscore).
+// INLINE_OPTIMIZED_FUNCTION_LIST defines the intrinsics typically handled
+// specially by Crankshaft.
// Entries have the form F(name, number of arguments, number of return values).
#define INLINE_OPTIMIZED_FUNCTION_LIST(F) \
/* Typed Arrays */ \
F(GetPrototype, 1, 1)
+#define FOR_EACH_INTRINSIC(F) \
+ RUNTIME_FUNCTION_LIST(F) \
+ INLINE_FUNCTION_LIST(F) \
+ INLINE_OPTIMIZED_FUNCTION_LIST(F)
+
//---------------------------------------------------------------------------
// Runtime provides access to all C++ runtime functions.
enum FunctionId {
#define F(name, nargs, ressize) k##name,
#define I(name, nargs, ressize) kInline##name,
- RUNTIME_FUNCTION_LIST(F) INLINE_FUNCTION_LIST(F)
- INLINE_OPTIMIZED_FUNCTION_LIST(F) RUNTIME_FUNCTION_LIST(I)
- INLINE_FUNCTION_LIST(I) INLINE_OPTIMIZED_FUNCTION_LIST(I)
+ FOR_EACH_INTRINSIC(F) FOR_EACH_INTRINSIC(I)
#undef I
#undef F
- kNumFunctions,
- // TODO(svenpanne) The values below are cruel hacks, remove them!
- kFirstInlineFunction = kInlineIsSmi,
- kLastInlineFunction = kInlineDebugIsActive
+ kNumFunctions,
};
enum IntrinsicType { RUNTIME, INLINE };
#define RUNTIME_ENTRY(name, i1, i2) \
{ Runtime::k##name, "Runtime::" #name } \
,
- RUNTIME_FUNCTION_LIST(RUNTIME_ENTRY) INLINE_FUNCTION_LIST(RUNTIME_ENTRY)
- INLINE_OPTIMIZED_FUNCTION_LIST(RUNTIME_ENTRY)
+ FOR_EACH_INTRINSIC(RUNTIME_ENTRY)
#undef RUNTIME_ENTRY
};
void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
- InlineFunctionGenerator generator = FindInlineFunctionGenerator(expr);
- if (generator != nullptr) {
- Comment cmnt(masm_, "[ InlineRuntimeCall");
- EmitInlineRuntimeCall(expr, generator);
- return;
- }
-
- Comment cmnt(masm_, "[ CallRuntime");
ZoneList<Expression*>* args = expr->arguments();
int arg_count = args->length();
if (expr->is_jsruntime()) {
+ Comment cmnt(masm_, "[ CallRuntime");
// Push the builtins object as receiver.
__ movp(rax, GlobalObjectOperand());
__ Push(FieldOperand(rax, GlobalObject::kBuiltinsOffset));
context()->DropAndPlug(1, rax);
} else {
- // Push the arguments ("left-to-right").
- for (int i = 0; i < arg_count; i++) {
- VisitForStackValue(args->at(i));
- }
+ const Runtime::Function* function = expr->function();
+ switch (function->function_id) {
+#define CALL_INTRINSIC_GENERATOR(Name) \
+ case Runtime::kInline##Name: { \
+ Comment cmnt(masm_, "[ Inline" #Name); \
+ return Emit##Name(expr); \
+ }
+ FOR_EACH_FULL_CODE_INTRINSIC(CALL_INTRINSIC_GENERATOR)
+#undef CALL_INTRINSIC_GENERATOR
+ default: {
+ Comment cmnt(masm_, "[ CallRuntime for unhandled intrinsic");
+ // Push the arguments ("left-to-right").
+ for (int i = 0; i < arg_count; i++) {
+ VisitForStackValue(args->at(i));
+ }
- // Call the C runtime.
- __ CallRuntime(expr->function(), arg_count);
- context()->Plug(rax);
+ // Call the C runtime.
+ __ CallRuntime(function, arg_count);
+ context()->Plug(rax);
+ }
+ }
}
}
void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
- InlineFunctionGenerator generator = FindInlineFunctionGenerator(expr);
- if (generator != nullptr) {
- Comment cmnt(masm_, "[ InlineRuntimeCall");
- EmitInlineRuntimeCall(expr, generator);
- return;
- }
-
- Comment cmnt(masm_, "[ CallRuntime");
ZoneList<Expression*>* args = expr->arguments();
+ int arg_count = args->length();
if (expr->is_jsruntime()) {
+ Comment cmnt(masm_, "[ CallRuntime");
// Push the builtins object as receiver.
__ mov(eax, GlobalObjectOperand());
__ push(FieldOperand(eax, GlobalObject::kBuiltinsOffset));
__ push(Operand(esp, 0));
__ mov(Operand(esp, kPointerSize), eax);
- // Code common for calls using the IC.
- ZoneList<Expression*>* args = expr->arguments();
- int arg_count = args->length();
+ // Push the arguments ("left-to-right").
for (int i = 0; i < arg_count; i++) {
VisitForStackValue(args->at(i));
}
context()->DropAndPlug(1, eax);
} else {
- // Push the arguments ("left-to-right").
- int arg_count = args->length();
- for (int i = 0; i < arg_count; i++) {
- VisitForStackValue(args->at(i));
- }
-
- // Call the C runtime function.
- __ CallRuntime(expr->function(), arg_count);
+ const Runtime::Function* function = expr->function();
+ switch (function->function_id) {
+#define CALL_INTRINSIC_GENERATOR(Name) \
+ case Runtime::kInline##Name: { \
+ Comment cmnt(masm_, "[ Inline" #Name); \
+ return Emit##Name(expr); \
+ }
+ FOR_EACH_FULL_CODE_INTRINSIC(CALL_INTRINSIC_GENERATOR)
+#undef CALL_INTRINSIC_GENERATOR
+ default: {
+ Comment cmnt(masm_, "[ CallRuntime for unhandled intrinsic");
+ // Push the arguments ("left-to-right").
+ for (int i = 0; i < arg_count; i++) {
+ VisitForStackValue(args->at(i));
+ }
- context()->Plug(eax);
+ // Call the C runtime function.
+ __ CallRuntime(expr->function(), arg_count);
+ context()->Plug(eax);
+ }
+ }
}
}