Bug 1641708 - Support IsCallable in CacheIR r=jandem
authorTom Schuster <evilpies@gmail.com>
Fri, 29 May 2020 16:17:32 +0000
changeset 533021 a1b906385cfff40825bb71fc0e6bf447efa332c3
parent 533020 b6d02786fcdc9ee79f126318433473195c05d083
child 533022 489bd543dc6f4ee686681e2bdb537f3cdb651f7d
push id37461
push userccoroiu@mozilla.com
push dateFri, 29 May 2020 21:46:31 +0000
treeherdermozilla-central@a58cc68b0c51 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjandem
bugs1641708
milestone78.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1641708 - Support IsCallable in CacheIR r=jandem Differential Revision: https://phabricator.services.mozilla.com/D77381
js/src/jit/CacheIR.cpp
js/src/jit/CacheIR.h
js/src/jit/CacheIRCompiler.cpp
js/src/jit/CacheIROps.yaml
--- a/js/src/jit/CacheIR.cpp
+++ b/js/src/jit/CacheIR.cpp
@@ -5004,17 +5004,17 @@ AttachDecision CallIRGenerator::tryAttac
   // Need a single argument.
   if (argc_ != 1) {
     return AttachDecision::NoAction;
   }
 
   // Initialize the input operand.
   Int32OperandId argcId(writer.setInputOperandId(0));
 
-  // Guard callee is the 'isArray' intrinsic native function.
+  // Guard callee is the 'isArray' native function.
   emitNativeCalleeGuard(callee);
 
   // Check if the argument is an Array and return result.
   ValOperandId argId = writer.loadArgumentFixedSlot(ArgumentKind::Arg0, argc_);
   writer.isArrayResult(argId);
 
   // This stub does not need to be monitored, because it always
   // returns a boolean.
@@ -5165,16 +5165,41 @@ AttachDecision CallIRGenerator::tryAttac
   // returns a boolean.
   writer.returnFromIC();
   cacheIRStubKind_ = BaselineCacheIRStubKind::Regular;
 
   trackAttached("IsObject");
   return AttachDecision::Attach;
 }
 
+AttachDecision CallIRGenerator::tryAttachIsCallable(HandleFunction callee) {
+  // Need a single argument.
+  if (argc_ != 1) {
+    return AttachDecision::NoAction;
+  }
+
+  // Initialize the input operand.
+  Int32OperandId argcId(writer.setInputOperandId(0));
+
+  // Guard callee is the 'IsCallable' intrinsic native function.
+  emitNativeCalleeGuard(callee);
+
+  // Check if the argument is callable and return result.
+  ValOperandId argId = writer.loadArgumentFixedSlot(ArgumentKind::Arg0, argc_);
+  writer.isCallableResult(argId);
+
+  // This stub does not need to be monitored, because it always
+  // returns a boolean.
+  writer.returnFromIC();
+  cacheIRStubKind_ = BaselineCacheIRStubKind::Regular;
+
+  trackAttached("IsCallable");
+  return AttachDecision::Attach;
+}
+
 AttachDecision CallIRGenerator::tryAttachStringChar(HandleFunction callee,
                                                     StringChar kind) {
   // Need one argument.
   if (argc_ != 1) {
     return AttachDecision::NoAction;
   }
 
   if (!CanAttachStringChar(thisval_, args_[0], kind)) {
@@ -5603,16 +5628,18 @@ AttachDecision CallIRGenerator::tryAttac
     case InlinableNative::IntrinsicToString:
       return tryAttachToString(callee);
     case InlinableNative::IntrinsicToObject:
       return tryAttachToObject(callee);
     case InlinableNative::IntrinsicToInteger:
       return tryAttachToInteger(callee);
     case InlinableNative::IntrinsicIsObject:
       return tryAttachIsObject(callee);
+    case InlinableNative::IntrinsicIsCallable:
+      return tryAttachIsCallable(callee);
 
     // String natives.
     case InlinableNative::StringCharCodeAt:
       return tryAttachStringCharCodeAt(callee);
     case InlinableNative::StringCharAt:
       return tryAttachStringCharAt(callee);
 
     // Math natives.
--- a/js/src/jit/CacheIR.h
+++ b/js/src/jit/CacheIR.h
@@ -1521,16 +1521,17 @@ class MOZ_RAII CallIRGenerator : public 
   AttachDecision tryAttachArrayPush(HandleFunction callee);
   AttachDecision tryAttachArrayJoin(HandleFunction callee);
   AttachDecision tryAttachArrayIsArray(HandleFunction callee);
   AttachDecision tryAttachIsSuspendedGenerator(HandleFunction callee);
   AttachDecision tryAttachToString(HandleFunction callee);
   AttachDecision tryAttachToObject(HandleFunction callee);
   AttachDecision tryAttachToInteger(HandleFunction callee);
   AttachDecision tryAttachIsObject(HandleFunction callee);
+  AttachDecision tryAttachIsCallable(HandleFunction callee);
   AttachDecision tryAttachStringChar(HandleFunction callee, StringChar kind);
   AttachDecision tryAttachStringCharCodeAt(HandleFunction callee);
   AttachDecision tryAttachStringCharAt(HandleFunction callee);
   AttachDecision tryAttachMathAbs(HandleFunction callee);
   AttachDecision tryAttachMathFloor(HandleFunction callee);
   AttachDecision tryAttachMathCeil(HandleFunction callee);
   AttachDecision tryAttachMathRound(HandleFunction callee);
   AttachDecision tryAttachMathSqrt(HandleFunction callee);
--- a/js/src/jit/CacheIRCompiler.cpp
+++ b/js/src/jit/CacheIRCompiler.cpp
@@ -3703,16 +3703,59 @@ bool CacheIRCompiler::emitIsObjectResult
   ValueOperand val = allocator.useValueRegister(masm, inputId);
 
   masm.testObjectSet(Assembler::Equal, val, scratch);
 
   EmitStoreResult(masm, scratch, JSVAL_TYPE_BOOLEAN, output);
   return true;
 }
 
+bool CacheIRCompiler::emitIsCallableResult(ValOperandId inputId) {
+  JitSpew(JitSpew_Codegen, "%s", __FUNCTION__);
+
+  AutoOutputRegister output(*this);
+  AutoScratchRegister scratch1(allocator, masm);
+  AutoScratchRegisterMaybeOutput scratch2(allocator, masm, output);
+
+  ValueOperand val = allocator.useValueRegister(masm, inputId);
+
+  Label isObject, done;
+  masm.branchTestObject(Assembler::Equal, val, &isObject);
+  // Primitives are never callable.
+  masm.move32(Imm32(0), scratch2);
+  masm.jump(&done);
+
+  masm.bind(&isObject);
+  masm.unboxObject(val, scratch1);
+
+  Label isProxy;
+  masm.isCallable(scratch1, scratch2, &isProxy);
+  masm.jump(&done);
+
+  masm.bind(&isProxy);
+  {
+    LiveRegisterSet volatileRegs(GeneralRegisterSet::Volatile(),
+                                 liveVolatileFloatRegs());
+    masm.PushRegsInMask(volatileRegs);
+
+    masm.setupUnalignedABICall(scratch2);
+    masm.passABIArg(scratch1);
+    masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, ObjectIsCallable));
+    masm.storeCallBoolResult(scratch2);
+
+    LiveRegisterSet ignore;
+    ignore.add(scratch2);
+    masm.PopRegsInMaskIgnore(volatileRegs, ignore);
+  }
+
+  masm.bind(&done);
+  EmitStoreResult(masm, scratch2, JSVAL_TYPE_BOOLEAN, output);
+  return true;
+}
+
 bool CacheIRCompiler::emitMathAbsInt32Result(Int32OperandId inputId) {
   JitSpew(JitSpew_Codegen, "%s", __FUNCTION__);
 
   AutoOutputRegister output(*this);
   AutoScratchRegisterMaybeOutput scratch(allocator, masm, output);
 
   Register input = allocator.useRegister(masm, inputId);
 
--- a/js/src/jit/CacheIROps.yaml
+++ b/js/src/jit/CacheIROps.yaml
@@ -674,16 +674,22 @@
     input: ValId
 
 - name: IsObjectResult
   shared: true
   transpile: true
   args:
     input: ValId
 
+- name: IsCallableResult
+  shared: true
+  transpile: false
+  args:
+    input: ValId
+
 - name: MathAbsInt32Result
   shared: true
   transpile: true
   args:
     input: Int32Id
 
 - name: MathAbsNumberResult
   shared: true