From: kasperl@chromium.org Date: Mon, 29 Jun 2009 08:14:06 +0000 (+0000) Subject: Optimize %IsConstructCall() on IA-32. X-Git-Tag: upstream/4.7.83~23796 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=a1622491af3e01fde5df288d9f6b4e1f8b7a304c;p=platform%2Fupstream%2Fv8.git Optimize %IsConstructCall() on IA-32. Review URL: http://codereview.chromium.org/150018 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@2290 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- diff --git a/src/arm/codegen-arm.cc b/src/arm/codegen-arm.cc index 6626619..eeea560 100644 --- a/src/arm/codegen-arm.cc +++ b/src/arm/codegen-arm.cc @@ -3290,6 +3290,14 @@ void CodeGenerator::GenerateIsArray(ZoneList* args) { } +void CodeGenerator::GenerateIsConstructCall(ZoneList* args) { + VirtualFrame::SpilledScope spilled_scope; + ASSERT(args->length() == 0); + frame_->CallRuntime(Runtime::kIsConstructCall, 0); + frame_->EmitPush(r0); +} + + void CodeGenerator::GenerateArgumentsLength(ZoneList* args) { VirtualFrame::SpilledScope spilled_scope; ASSERT(args->length() == 0); diff --git a/src/arm/codegen-arm.h b/src/arm/codegen-arm.h index 4fab900..2048a17 100644 --- a/src/arm/codegen-arm.h +++ b/src/arm/codegen-arm.h @@ -333,6 +333,9 @@ class CodeGenerator: public AstVisitor { void GenerateIsNonNegativeSmi(ZoneList* args); void GenerateIsArray(ZoneList* args); + // Support for construct call checks. + void GenerateIsConstructCall(ZoneList* args); + // Support for arguments.length and arguments[?]. void GenerateArgumentsLength(ZoneList* args); void GenerateArgumentsAccess(ZoneList* args); diff --git a/src/codegen.cc b/src/codegen.cc index ad5b1ea..6a41b9d 100644 --- a/src/codegen.cc +++ b/src/codegen.cc @@ -416,6 +416,7 @@ CodeGenerator::InlineRuntimeLUT CodeGenerator::kInlineRuntimeLUT[] = { {&CodeGenerator::GenerateIsSmi, "_IsSmi"}, {&CodeGenerator::GenerateIsNonNegativeSmi, "_IsNonNegativeSmi"}, {&CodeGenerator::GenerateIsArray, "_IsArray"}, + {&CodeGenerator::GenerateIsConstructCall, "_IsConstructCall"}, {&CodeGenerator::GenerateArgumentsLength, "_ArgumentsLength"}, {&CodeGenerator::GenerateArgumentsAccess, "_Arguments"}, {&CodeGenerator::GenerateValueOf, "_ValueOf"}, diff --git a/src/date-delay.js b/src/date-delay.js index 0a89783..18d58d5 100644 --- a/src/date-delay.js +++ b/src/date-delay.js @@ -424,7 +424,7 @@ function TimeClip(time) { %SetCode($Date, function(year, month, date, hours, minutes, seconds, ms) { - if (%IsConstructCall()) { + if (%_IsConstructCall()) { // ECMA 262 - 15.9.3 var argc = %_ArgumentsLength(); if (argc == 0) { diff --git a/src/ia32/codegen-ia32.cc b/src/ia32/codegen-ia32.cc index 59c1d45..fa407c2 100644 --- a/src/ia32/codegen-ia32.cc +++ b/src/ia32/codegen-ia32.cc @@ -4987,6 +4987,29 @@ void CodeGenerator::GenerateIsArray(ZoneList* args) { } +void CodeGenerator::GenerateIsConstructCall(ZoneList* args) { + ASSERT(args->length() == 0); + + // Get the frame pointer for the calling frame. + Result fp = allocator()->Allocate(); + __ mov(fp.reg(), Operand(ebp, StandardFrameConstants::kCallerFPOffset)); + + // Skip the arguments adaptor frame if it exists. + Label check_frame_marker; + __ cmp(Operand(fp.reg(), StandardFrameConstants::kContextOffset), + Immediate(ArgumentsAdaptorFrame::SENTINEL)); + __ j(not_equal, &check_frame_marker); + __ mov(fp.reg(), Operand(fp.reg(), StandardFrameConstants::kCallerFPOffset)); + + // Check the marker in the calling frame. + __ bind(&check_frame_marker); + __ cmp(Operand(fp.reg(), StandardFrameConstants::kMarkerOffset), + Immediate(Smi::FromInt(StackFrame::CONSTRUCT))); + fp.Unuse(); + destination()->Split(equal); +} + + void CodeGenerator::GenerateArgumentsLength(ZoneList* args) { ASSERT(args->length() == 0); // ArgumentsAccessStub takes the parameter count as an input argument diff --git a/src/ia32/codegen-ia32.h b/src/ia32/codegen-ia32.h index d25d07c..a7e0b06 100644 --- a/src/ia32/codegen-ia32.h +++ b/src/ia32/codegen-ia32.h @@ -522,6 +522,9 @@ class CodeGenerator: public AstVisitor { void GenerateIsNonNegativeSmi(ZoneList* args); void GenerateIsArray(ZoneList* args); + // Support for construct call checks. + void GenerateIsConstructCall(ZoneList* args); + // Support for arguments.length and arguments[?]. void GenerateArgumentsLength(ZoneList* args); void GenerateArgumentsAccess(ZoneList* args); diff --git a/src/messages.js b/src/messages.js index ec4b352..bef5540 100644 --- a/src/messages.js +++ b/src/messages.js @@ -659,7 +659,7 @@ function DefineError(f) { %SetProperty(f.prototype, 'constructor', f, DONT_ENUM); f.prototype.name = name; %SetCode(f, function(m) { - if (%IsConstructCall()) { + if (%_IsConstructCall()) { if (m === kAddMessageAccessorsMarker) { DefineOneShotAccessor(this, 'message', function (obj) { return FormatMessage({type: obj.type, args: obj.arguments}); diff --git a/src/regexp-delay.js b/src/regexp-delay.js index 8491863..14c3644 100644 --- a/src/regexp-delay.js +++ b/src/regexp-delay.js @@ -103,7 +103,7 @@ function DoConstructRegExp(object, pattern, flags, isConstructorCall) { function RegExpConstructor(pattern, flags) { - if (%IsConstructCall()) { + if (%_IsConstructCall()) { DoConstructRegExp(this, pattern, flags, true); } else { // RegExp : Called as function; see ECMA-262, section 15.10.3.1. diff --git a/src/string.js b/src/string.js index 3d8a11b..604f925 100644 --- a/src/string.js +++ b/src/string.js @@ -35,7 +35,7 @@ // Set the String function and constructor. %SetCode($String, function(x) { var value = %_ArgumentsLength() == 0 ? '' : ToString(x); - if (%IsConstructCall()) { + if (%_IsConstructCall()) { %_SetValueOf(this, value); } else { return value; diff --git a/src/v8natives.js b/src/v8natives.js index fe46351..97363e9 100644 --- a/src/v8natives.js +++ b/src/v8natives.js @@ -154,7 +154,7 @@ function SetupGlobal() { // ECMA-262 - 15.1.1.3. %SetProperty(global, "undefined", void 0, DONT_ENUM | DONT_DELETE); - + // Setup non-enumerable function on the global object. InstallFunctions(global, DONT_ENUM, $Array( "isNaN", GlobalIsNaN, @@ -174,7 +174,7 @@ SetupGlobal(); %SetCode($Boolean, function(x) { - if (%IsConstructCall()) { + if (%_IsConstructCall()) { %_SetValueOf(this, ToBoolean(x)); } else { return ToBoolean(x); @@ -273,7 +273,7 @@ function ObjectLookupSetter(name) { %SetCode($Object, function(x) { - if (%IsConstructCall()) { + if (%_IsConstructCall()) { if (x == null) return this; return ToObject(x); } else { @@ -350,7 +350,7 @@ SetupBoolean(); // Set the Number function and constructor. %SetCode($Number, function(x) { var value = %_ArgumentsLength() == 0 ? 0 : ToNumber(x); - if (%IsConstructCall()) { + if (%_IsConstructCall()) { %_SetValueOf(this, value); } else { return value; @@ -570,4 +570,3 @@ function SetupFunction() { } SetupFunction(); - diff --git a/src/x64/codegen-x64.cc b/src/x64/codegen-x64.cc index fc196ce..24e3ec3 100644 --- a/src/x64/codegen-x64.cc +++ b/src/x64/codegen-x64.cc @@ -3330,6 +3330,14 @@ void CodeGenerator::GenerateIsArray(ZoneList* args) { } +void CodeGenerator::GenerateIsConstructCall(ZoneList* args) { + // TODO(X64): Optimize this like it's done on IA-32. + ASSERT(args->length() == 0); + Result answer = frame_->CallRuntime(Runtime::kIsConstructCall, 0); + frame_->Push(&answer); +} + + void CodeGenerator::GenerateArgumentsLength(ZoneList* args) { ASSERT(args->length() == 0); // ArgumentsAccessStub takes the parameter count as an input argument diff --git a/src/x64/codegen-x64.h b/src/x64/codegen-x64.h index af82de8..a174c51 100644 --- a/src/x64/codegen-x64.h +++ b/src/x64/codegen-x64.h @@ -522,6 +522,9 @@ class CodeGenerator: public AstVisitor { void GenerateIsNonNegativeSmi(ZoneList* args); void GenerateIsArray(ZoneList* args); + // Support for construct call checks. + void GenerateIsConstructCall(ZoneList* args); + // Support for arguments.length and arguments[?]. void GenerateArgumentsLength(ZoneList* args); void GenerateArgumentsAccess(ZoneList* args);