Beispiel #1
0
bool eval_get_call_info_static_method_hook(MethodCallPackage &info,
                                           bool &foundClass) {
  if (!hhvm) {
    ASSERT(!foundClass);
    ClassEvalState *ce;
    const MethodStatementWrapper *msw =
      Eval::RequestEvalState::findMethod(info.rootCls, *info.name, ce, true);
    foundClass = (ce != NULL);
    if (msw) {
      info.ci = msw->m_methodStatement->getCallInfo();
      info.extra = (void*)msw;
      eval_set_callee_alias(*info.name);
      return true;
    }

    if (ce) {
      if (ce->getAttributes() & ObjectData::HasCallStatic) {
        info.obj = 0;
        info.ci = ObjectData::GetCallHandler();
        return true;
      }
    }
  }
  return false;
}
Variant StaticMethodExpression::eval(VariableEnvironment &env) const {
  SET_LINE;
  // Static method expressions can be object method expressions inside
  // of a method when an object is available and the object's class inherits.
  // Super slow.
  String cname = m_cname->get(env);
  bool sp = m_cname->isSp();
  String name(m_name->get(env));
  Variant &vco = env.currentObject();
  Object co;
  if (!vco.isNull()) co = vco.toObject();
  bool withinClass = !co.isNull() && co->o_instanceof(cname.data());
  bool foundClass;
  const MethodStatement *ms = RequestEvalState::findMethod(cname.data(),
                                                           name.data(),
                                                           foundClass);
  if (withinClass) {
    if (m_construct) {
      String name = cname;
      while (true) {
        ClassEvalState *ces = RequestEvalState::findClassState(name.data());
        if (!ces) {
          // possibly built in
          cname = name;
          break;
        }
        // Ugly but needed to populate the method table for the parent
        ces->initializeInstance();
        ms = ces->getConstructor();
        if (ms) break;
        name = ces->getClass()->parent().c_str();
        if (name.empty()) break;
      }
    }
    if (!ms) {
      Array params = getParams(env);
      EvalFrameInjection::EvalStaticClassNameHelper helper(cname, sp);
      return ref(co->o_invoke_ex(cname, name, params));
    } else if (!(ms->getModifiers() & ClassStatement::Static)) {
      EvalFrameInjection::EvalStaticClassNameHelper helper(cname, sp);
      return ref(ms->invokeInstanceDirect(co, env, this));
    }
  }
  if (ms) {
    EvalFrameInjection::EvalStaticClassNameHelper helper(cname, sp);
    return ref(ms->invokeStaticDirect(cname.data(), env, this));
  }
  Array params = getParams(env);
  EvalFrameInjection::EvalStaticClassNameHelper helper(cname, sp);
  return ref(invoke_static_method(cname.data(), name.data(), params));
}
Beispiel #3
0
bool eval_get_call_info_static_method_hook(MethodCallPackage &info,
                                           bool &foundClass) {
  ASSERT(!foundClass);
  const MethodStatement *ms =
    Eval::RequestEvalState::findMethod(info.rootCls->data(),
      info.name->data(), foundClass, true);
  if (ms) {
    info.ci = ms->getCallInfo();
    info.extra = (void*)ms;
    return true;
  }

  if (foundClass) {
    ClassEvalState *ce = Eval::RequestEvalState::findClassState(info.rootCls);
    if (ce->getAttributes() & ObjectData::HasCallStatic) {
      info.obj = 0;
      info.ci = ObjectData::GetCallHandler();
      return true;
    }
  }
  return false;
}
Variant StaticMethodExpression::eval(VariableEnvironment &env) const {
  SET_LINE;
  // Static method expressions can be object method expressions inside
  // of a method when an object is available and the object's class inherits.
  // Super slow.
  String cname = m_cname->get(env);
  bool sp = m_cname->isSp();
  String name(m_name->get(env));
  Variant &vco = env.currentObject();
  Object co;
  if (!vco.isNull()) co = vco.toObject();
  bool withinClass = !co.isNull() && co->o_instanceof(cname.data());
  bool foundClass;
  const MethodStatement *ms = RequestEvalState::findMethod(cname.data(),
                                                           name.data(),
                                                           foundClass);
  if (withinClass) {
    if (m_construct) {
      String name = cname;
      while (true) {
        ClassEvalState *ces = RequestEvalState::findClassState(name.data());
        if (!ces) {
          // possibly built in
          cname = name;
          break;
        }
        // Ugly but needed to populate the method table for the parent
        ces->initializeInstance();
        ms = ces->getConstructor();
        if (ms) break;
        name = ces->getClass()->parent().c_str();
        if (name.empty()) break;
      }
    }
    if (!ms) {
      Array params = getParams(env);
      EvalFrameInjection::EvalStaticClassNameHelper helper(cname, sp);
      return strongBind(co->o_invoke_ex(cname, name, params));
    } else if (!(ms->getModifiers() & ClassStatement::Static)) {
      EvalFrameInjection::EvalStaticClassNameHelper helper(cname, sp);
      return strongBind(ms->invokeInstanceDirect(co, env, this));
    }
  }
  if (ms) {
    return strongBind(ms->invokeStaticDirect(cname, env, this, sp));
  }

  // Handle builtins
  MethodCallPackage mcp1;
  mcp1.dynamicNamedCall(cname, name, -1);
  const CallInfo* cit1 = mcp1.ci;
  // If the lookup failed dynamicNamedCall() must throw an exception,
  // so if we reach here cit1 must not be NULL
  ASSERT(cit1);
  ArrayInit ai(m_params.size(), true);
  for (unsigned int i = 0; i < m_params.size(); ++i) {
    if (cit1->mustBeRef(i)) {
      ai.setRef(m_params[i]->refval(env));
    } else if (cit1->isRef(i)) {
      ai.setRef(m_params[i]->refval(env, 0));
    } else {
      ai.set(m_params[i]->eval(env));
    }
  }
  return strongBind((cit1->getMeth())(mcp1, Array(ai.create())));
}