/** * 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; }
/** * 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; }
/** * 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; }