Exemplo n.º 1
0
 /**
  * Retrieves/Creates a function cache for a function call
  *
  * @param string $functionName
  * @param Call $call
  * @param CompilationContext $compilationContext
  * @param boolean $exists
  */
 public function get($functionName, CompilationContext $compilationContext, Call $call, $exists)
 {
     if (isset($this->cache[$functionName])) {
         return $this->cache[$functionName] . ', ' . SlotsCache::getExistingFunctionSlot($functionName);
     }
     if (!$exists) {
         return 'NULL, 0';
     }
     $cacheSlot = SlotsCache::getFunctionSlot($functionName);
     $number = 0;
     if (!$compilationContext->insideCycle) {
         $gatherer = $this->gatherer;
         if ($gatherer) {
             $number = $gatherer->getNumberOfFunctionCalls($functionName);
             if ($number <= 1) {
                 return 'NULL, ' . $cacheSlot;
             }
         }
     }
     if ($compilationContext->insideCycle || $number > 1) {
         $functionCacheVariable = $compilationContext->symbolTable->getTempVariableForWrite('zephir_fcall_cache_entry', $compilationContext);
         $functionCacheVariable->setMustInitNull(true);
         $functionCacheVariable->setReusable(false);
         $functionCache = '&' . $functionCacheVariable->getName();
     } else {
         $functionCache = 'NULL';
     }
     $this->cache[$functionName] = $functionCache;
     return $functionCache . ', ' . $cacheSlot;
 }
Exemplo n.º 2
0
 /**
  * MethodCache
  *
  * @param CompilationContext $compilationContext
  * @param ClassMethod|\ReflectionMethod $method
  * @param boolean $allowNtsCache
  */
 public function get(CompilationContext $compilationContext, $method, $allowNtsCache = true)
 {
     if (!is_object($method)) {
         return 'NULL, 0';
     }
     if (!$method instanceof \ReflectionMethod) {
         $completeName = $method->getClassDefinition()->getCompleteName();
         /**
          * Avoid generate caches for external classes
          */
         if ($method->getClassDefinition()->isExternal()) {
             return 'NULL, 0';
         }
         if (isset($this->cache[$completeName][$method->getName()])) {
             return '&' . $this->cache[$completeName][$method->getName()]->getName() . ', ' . SlotsCache::getExistingMethodSlot($method);
         }
         if ($method->getClassDefinition()->isInterface()) {
             return 'NULL, 0';
         }
     }
     $mustBeCached = false;
     if (!$compilationContext->insideCycle) {
         if (!$method instanceof \ReflectionMethod) {
             $classDefinition = $method->getClassDefinition();
             if (!$classDefinition->isBundled() && $allowNtsCache) {
                 $mustBeCached = true;
             } else {
                 if (!$method->isPrivate() && !$method->isFinal()) {
                     return 'NULL, 0';
                 }
             }
         } else {
             if (!$method->isPrivate() && !$method->isFinal()) {
                 return 'NULL, 0';
             }
         }
     }
     $functionCache = $compilationContext->symbolTable->getTempVariableForWrite('zephir_fcall_cache_entry', $compilationContext);
     if ($method->isPrivate() || $method->isFinal() || $mustBeCached) {
         $cacheSlot = SlotsCache::getMethodSlot($method);
     } else {
         $cacheSlot = '0';
     }
     $functionCache->setMustInitNull(true);
     $functionCache->setReusable(false);
     if (!$method instanceof \ReflectionMethod) {
         $this->cache[$completeName][$method->getName()] = $functionCache;
     }
     return '&' . $functionCache->getName() . ', ' . $cacheSlot;
 }
Exemplo n.º 3
0
 /**
  * Retrieves/Creates a function cache for a method call
  *
  * @param CompilationContext $compilationContext
  * @param ClassMethod $method
  * @param Variable $caller
  */
 public function get(CompilationContext $compilationContext, $methodName, Variable $caller)
 {
     $compiler = $compilationContext->compiler;
     $numberPoly = 0;
     if ($caller->getRealName() == 'this') {
         $classDefinition = $compilationContext->classDefinition;
         if ($classDefinition->hasMethod($methodName)) {
             $numberPoly++;
             $method = $classDefinition->getMethod($methodName);
         }
     } else {
         $classTypes = $caller->getClassTypes();
         foreach ($classTypes as $classType) {
             if ($compiler->isClass($classType) || $compiler->isInterface($classType) || $compiler->isBundledClass($classType) || $compiler->isBundledInterface($classType)) {
                 if ($compiler->isInterface($classType)) {
                     continue;
                 }
                 if ($compiler->isClass($classType)) {
                     $classDefinition = $compiler->getClassDefinition($classType);
                 } else {
                     $classDefinition = $compiler->getInternalClassDefinition($classType);
                 }
                 if (!$classDefinition) {
                     continue;
                 }
                 if ($classDefinition->hasMethod($methodName) && !$classDefinition->isInterface()) {
                     $numberPoly++;
                     $method = $classDefinition->getMethod($methodName);
                 }
             }
         }
     }
     if (!$numberPoly) {
         // Try to generate a cache based on the fact the variable is not modified within the loop block
         if ($compilationContext->insideCycle && !$caller->isTemporal()) {
             if (count($compilationContext->cycleBlocks) && $caller->getType() == 'variable') {
                 $currentBlock = $compilationContext->cycleBlocks[count($compilationContext->cycleBlocks) - 1];
                 if ($currentBlock->getMutateGatherer(true)->getNumberOfMutations($caller->getName()) == 0) {
                     $functionCache = $compilationContext->symbolTable->getTempVariableForWrite('zephir_fcall_cache_entry', $compilationContext);
                     $functionCache->setMustInitNull(true);
                     $functionCache->setReusable(false);
                     return '&' . $functionCache->getName() . ', 0';
                 }
             }
         }
         return 'NULL, 0';
     }
     if (!$method instanceof \ReflectionMethod) {
         if ($method->getClassDefinition()->isExternal()) {
             return 'NULL, 0';
         }
         $completeName = $method->getClassDefinition()->getCompleteName();
         if (isset($this->cache[$completeName][$method->getName()])) {
             return $this->cache[$completeName][$method->getName()] . ', ' . SlotsCache::getExistingMethodSlot($method);
         }
         $gatherer = $this->gatherer;
         if (is_object($gatherer)) {
             $number = $gatherer->getNumberOfMethodCalls($method->getClassDefinition()->getCompleteName(), $method->getName());
         } else {
             $number = 0;
         }
         $staticCacheable = !$method->getClassDefinition()->isInterface() && ($compilationContext->currentMethod == $method || $method->getClassDefinition()->isFinal() || $method->isFinal() || $method->isPrivate());
         if ($number > 1 || $compilationContext->insideCycle) {
             $cacheable = true;
         } else {
             $cacheable = false;
         }
     } else {
         $staticCacheable = false;
         $cacheable = false;
     }
     // Recursive methods require warm-up
     if ($compilationContext->currentMethod == $method) {
         if (!$compilationContext->methodWarmUp) {
             $compilationContext->methodWarmUp = new MethodCallWarmUp();
         }
     }
     $associatedClass = false;
     if ($caller->getName() != 'this_ptr') {
         $associatedClass = $caller->getAssociatedClass();
         if ($this->isClassCacheable($associatedClass)) {
             $staticCacheable = true;
         }
     }
     if ($staticCacheable) {
         $cacheSlot = SlotsCache::getMethodSlot($method);
     } else {
         $cacheSlot = '0';
     }
     if ($cacheable) {
         $functionCacheVar = $compilationContext->symbolTable->getTempVariableForWrite('zephir_fcall_cache_entry', $compilationContext);
         $functionCacheVar->setMustInitNull(true);
         $functionCacheVar->setReusable(false);
         $functionCache = '&' . $functionCacheVar->getName();
     } else {
         $functionCache = 'NULL';
     }
     if (!$method instanceof \ReflectionMethod) {
         $this->cache[$completeName][$method->getName()] = $functionCache;
     }
     return $functionCache . ', ' . $cacheSlot;
 }