void CommandTerminal::parseParams() {
    
    if(g_serialString.length() > 0) {
        
        clearParams();
        // Command strings will look like:
        //    x:3|y:0|r:255|g:255|b:128
        //    x:4|y:0|r:255|g:128|b:128
        //    x:5|y:0|r:234|g:188|b:164
        //    x:6|y:0|r:234|g:188|b:164
              
        // First split by paramDelim
        const int kMaxCommands = 16;
        int pipeIndexex[kMaxCommands] = {};

        int pipeIndex = -1;
        for(int x = 0; x < 16; x++) {
          pipeIndex = g_serialString.indexOf(paramDelim);
          if (pipeIndex > -1) {
            // get text left of index
            String cmdSet = g_serialString.substring(0, pipeIndex);
            appendParam(cmdSet, x);
      
            // Remove cmdSet from g_serialString
            String n = g_serialString.substring(pipeIndex+1);
            g_serialString = n;
          } else {
            // Last command
            appendParam(g_serialString, x);
            g_serialString = "";
            break;
          }
        }
    }
}
示例#2
0
char *
test_freeParamArray()
{
	struct ParamArray *pa = newParamArray();
	struct Param *p1 = setUpTestParam();
	struct Param *p2 = setUpTestParam();
	appendParam(pa, p1);
	appendParam(pa, p2);

	freeParamArray(pa);

	mu_assert("freeParamArray() should free param array pointer witnout \
		  segfaulting", 1);

	return NULL;
}
示例#3
0
void FuncEmitter::setBuiltinFunc(const ClassInfo::MethodInfo* info,
                                 BuiltinFunction bif, BuiltinFunction nif,
                                 Offset base_) {
  assert(info);
  m_info = info;
  Attr attrs_ = AttrBuiltin;
  if (info->attribute & (ClassInfo::RefVariableArguments |
                         ClassInfo::MixedVariableArguments)) {
    attrs_ |= AttrVariadicByRef;
  }
  if (info->attribute & ClassInfo::IsReference) {
    attrs_ |= AttrReference;
  }
  if (info->attribute & ClassInfo::NoInjection) {
    attrs_ |= AttrNoInjection;
  }
  if (info->attribute & ClassInfo::NoFCallBuiltin) {
    attrs_ |= AttrNoFCallBuiltin;
  }
  if (info->attribute & ClassInfo::ParamCoerceModeNull) {
    attrs_ |= AttrParamCoerceModeNull;
  } else if (info->attribute & ClassInfo::ParamCoerceModeFalse) {
    attrs_ |= AttrParamCoerceModeFalse;
  }
  if (pce()) {
    if (info->attribute & ClassInfo::IsStatic) {
      attrs_ |= AttrStatic;
    }
    if (info->attribute & ClassInfo::IsFinal) {
      attrs_ |= AttrFinal;
    }
    if (info->attribute & ClassInfo::IsAbstract) {
      attrs_ |= AttrAbstract;
    }
    if (info->attribute & ClassInfo::IsPrivate) {
      attrs_ |= AttrPrivate;
    } else if (info->attribute & ClassInfo::IsProtected) {
      attrs_ |= AttrProtected;
    } else {
      attrs_ |= AttrPublic;
    }
  } else if (info->attribute & ClassInfo::AllowOverride) {
    attrs_ |= AttrAllowOverride;
  }

  returnType = info->returnType;
  docComment = makeStaticString(info->docComment);
  setLocation(0, 0);
  setBuiltinFunc(bif, nif, attrs_, base_);

  for (unsigned i = 0; i < info->parameters.size(); ++i) {
    // For builtin only, we use a dummy ParamInfo
    FuncEmitter::ParamInfo pi;
    const auto& parameter = info->parameters[i];
    pi.byRef = parameter->attribute & ClassInfo::IsReference;
    pi.builtinType = parameter->argType;
    appendParam(makeStaticString(parameter->name), pi);
  }
}
示例#4
0
void FuncEmitter::setBuiltinFunc(const ClassInfo::MethodInfo* info,
                                 BuiltinFunction bif, BuiltinFunction nif,
                                 Offset base) {
  assert(info);
  assert(bif);
  m_info = info;
  m_builtinFuncPtr = bif;
  m_nativeFuncPtr = nif;
  m_base = base;
  m_top = true;
  m_docComment = StringData::GetStaticString(info->docComment);
  m_line1 = 0;
  m_line2 = 0;
  m_attrs = AttrBuiltin | AttrSkipFrame;
  // TODO: Task #1137917: See if we can avoid marking most builtins with
  // "MayUseVV" and still make things work
  m_attrs = m_attrs | AttrMayUseVV;
  if (info->attribute & (ClassInfo::RefVariableArguments |
                         ClassInfo::MixedVariableArguments)) {
    m_attrs = m_attrs | AttrVariadicByRef;
  }
  if (info->attribute & ClassInfo::IsReference) {
    m_attrs = m_attrs | AttrReference;
  }
  if (info->attribute & ClassInfo::NoInjection) {
    m_attrs = m_attrs | AttrNoInjection;
  }
  if (pce()) {
    if (info->attribute & ClassInfo::IsStatic) {
      m_attrs = m_attrs | AttrStatic;
    }
    if (info->attribute & ClassInfo::IsFinal) {
      m_attrs = m_attrs | AttrFinal;
    }
    if (info->attribute & ClassInfo::IsAbstract) {
      m_attrs = m_attrs | AttrAbstract;
    }
    if (info->attribute & ClassInfo::IsPrivate) {
      m_attrs = m_attrs | AttrPrivate;
    } else if (info->attribute & ClassInfo::IsProtected) {
      m_attrs = m_attrs | AttrProtected;
    } else {
      m_attrs = m_attrs | AttrPublic;
    }
  } else if (info->attribute & ClassInfo::AllowOverride) {
    m_attrs = m_attrs | AttrAllowOverride;
  }

  m_returnType = info->returnType;
  for (unsigned i = 0; i < info->parameters.size(); ++i) {
    // For builtin only, we use a dummy ParamInfo
    FuncEmitter::ParamInfo pi;
    pi.setRef((bool)(info->parameters[i]->attribute & ClassInfo::IsReference));
    pi.setBuiltinType(info->parameters[i]->argType);
    appendParam(StringData::GetStaticString(info->parameters[i]->name), pi);
  }
}
// Add a character string with a specified length
void 
CatApiRequest::addConstParam (const char * value, const Lng32 length)
{
  // Allocate space for parameter and api structure
  char *param = new char [length + 1];  // 1 for null byte
  strncpy(param, value, length);
  param[length] = '\0';
  CatApiParam *newParam = new CatApiParam( param );

  // append to end of list
  appendParam(newParam);
}
示例#6
0
char *
test_getParam()
{
	struct ParamArray *pa = newParamArray();
	struct Param *p1 = setUpTestParam();
	struct Param *p2 = setUpTestParam();
	struct Param *ret = NULL;
	appendParam(pa, p1);
	appendParam(pa, p2);

	ret = getParam(pa, 2);
	mu_assert("getParam() should return NULL when passed index of entry \
		   known to NOT be in the array", !ret);

	ret = getParam(pa, 0);
	mu_assert("getParam() should not return NULL when passed index of \
		  entry known to be in array", ret);

	ret = getParam(pa, 1);

	return NULL;
}
// Add a character string that has single-quotes that have been doubled in
// preparation for a prepare query and so the length to be used
// in the request length of the string before the single-quotes were doubled.
void 
CatApiRequest::addConstParam (const Lng32 lengthForMsg, const char * value)
{
  size_t realLen = strlen(value);
  // Allocate space for parameter and api structure
  char *param = new char [realLen + 1];  // 1 for null byte
  strncpy(param, value, realLen);
  param[realLen] = '\0';
  CatApiParam *newParam = new CatApiParam( param, lengthForMsg );

  // append param to end of list of params
  appendParam(newParam);
}
示例#8
0
void FuncEmitter::setBuiltinFunc(const ClassInfo::MethodInfo* info,
                                 BuiltinFunction funcPtr, Offset base) {
  ASSERT(info);
  ASSERT(funcPtr);
  m_info = info;
  m_builtinFuncPtr = funcPtr;
  m_base = base;
  m_top = true;
  m_docComment = StringData::GetStaticString(info->docComment);
  m_line1 = 0;
  m_line2 = 0;
  m_attrs = AttrNone;
  // TODO: Task #1137917: See if we can avoid marking most builtins with
  // "MayUseVV" and still make things work
  m_attrs = (Attr)(m_attrs | AttrMayUseVV);
  if (info->attribute & (ClassInfo::RefVariableArguments |
                         ClassInfo::MixedVariableArguments)) {
    m_attrs = Attr(m_attrs | AttrVariadicByRef);
  }
  if (info->attribute & ClassInfo::IsReference) {
    m_attrs = (Attr)(m_attrs | AttrReference);
  }
  if (info->attribute & ClassInfo::NoInjection) {
    m_attrs = (Attr)(m_attrs | AttrNoInjection);
  }
  if (pce()) {
    if (info->attribute & ClassInfo::IsStatic) {
      m_attrs = (Attr)(m_attrs | AttrStatic);
    }
    if (info->attribute & ClassInfo::IsFinal) {
      m_attrs = (Attr)(m_attrs | AttrFinal);
    }
    if (info->attribute & ClassInfo::IsAbstract) {
      m_attrs = (Attr)(m_attrs | AttrAbstract);
    }
    if (info->attribute & ClassInfo::IsPrivate) {
      m_attrs = (Attr)(m_attrs | AttrPrivate);
    } else if (info->attribute & ClassInfo::IsProtected) {
      m_attrs = (Attr)(m_attrs | AttrProtected);
    } else {
      m_attrs = (Attr)(m_attrs | AttrPublic);
    }
  }

  for (unsigned i = 0; i < info->parameters.size(); ++i) {
    // For builtin only, we use a dummy ParamInfo
    FuncEmitter::ParamInfo pi;
    pi.setRef((bool)(info->parameters[i]->attribute & ClassInfo::IsReference));
    appendParam(StringData::GetStaticString(info->parameters[i]->name), pi);
  }
}
示例#9
0
/*
 * Warning:
 * The results of test_appendParam are dependent on the correct functioning
 * of newParamArray() and growParamArray()-- if the tests below  fail, please 
 * insure the correct functioning of these functions before debugging this code.
 * TODO: test structural integrity of added params under new setup (was 
 * confirmed under old, operation should be independent of what values param
 * struct has, but should be confirmed at some point)
 */
char *
test_appendParam()
{
	struct ParamArray *pa = newParamArray();
	struct Param *p1 = setUpTestParam();
	int i;

	appendParam(pa, p1);
	mu_assert("appendParam() should increment nElements appropriately",
		  pa->nElements == 1);
	mu_assert("appendParam() should not affect param array len when \
		  number of elements added is less than old len",
		  pa->len == PA_DEFAULT_SZ);
	mu_assert("first element in param array should not be null",
		  pa->data[0]);

	appendParam(pa, p1);
	mu_assert("appendParam() should increment nElements appropriately",
		  pa->nElements == 2);
	mu_assert("appendParam() should not affect param array len when \
		  number of elements added is less than old len",
		  pa->len == PA_DEFAULT_SZ);
	mu_assert("second element in param array should not be null",
		  pa->data[1]);
	for (i=0; i < 24; i++) {
		appendParam(pa, p1);
	}

	mu_assert("appendParam() should call growParamArray() to double size \
		  of array when nElements exceeds len",
		  pa->len == 2 * PA_DEFAULT_SZ);
	mu_assert("appendParam() should successfully append param past old \
		  len of the array", pa->data[25]); 

	return NULL;
}
示例#10
0
void Net<Dtype>::Init(const NetParameter& in_param){
	CHECK(Dragon::get_root_solver() || root_net)
		<< "Root net need to be set for all non-root solvers.";
	phase = in_param.state().phase();
	NetParameter filtered_param, param;
	//	filter for unqualified LayerParameters(e.g Test DataLayer)
	filterNet(in_param, &filtered_param);
	insertSplits(filtered_param, &param);
	name = param.name();
	LOG_IF(INFO, Dragon::get_root_solver())
		<< "Initialize net from parameters: ";/*<< endl << param.DebugString();*/
	map<string, int> blob_name_to_idx;
	set<string> available_blobs;
	CHECK_EQ(param.input_size(), param.input_shape_size())<< "input blob_shape must specify a blob.";
	memory_used = 0;
	//	check and stuff virtual input blobs firstly [Viewing Mode Only]
	for (int input_id=0; input_id < param.input_size(); input_id++){
		const int layer_id = -1;
		//	net_input.push_back(.....virtual blob.....)
		appendTop(param, layer_id, input_id, &available_blobs, &blob_name_to_idx);
	}
	//	stuff real blobs for each layer then [Traning/Testing/Viewing Mode]
	bottom_vecs.resize(param.layer_size());
	bottom_id_vecs.resize(param.layer_size());
	bottoms_need_backward.resize(param.layer_size());
	top_vecs.resize(param.layer_size());
	top_id_vecs.resize(param.layer_size());
	param_id_vecs.resize(param.layer_size());
	for (int layer_id = 0; layer_id < param.layer_size(); layer_id++){
		bool share_from_root = !Dragon::get_root_solver()
			&& root_net->layers[layer_id]->shareInParallel();
		//	copy net phase to layer if not set
		if (!param.layer(layer_id).has_phase())
			param.mutable_layer(layer_id)->set_phase(phase);
		const LayerParameter& layer_param = param.layer(layer_id);
		if (share_from_root){
			LOG(INFO) << "Share Layer: " << layer_param.name() << " from the root net.";
			//	share layer by pointer
			layers.push_back(root_net->layers[layer_id]);
			layers[layer_id]->setShared(true);
		}
		else{
			//	use layer factory to create a pointer
			//	layer type is referred by layer_param->type()
			//	see more in layer_factory.hpp
			layers.push_back(LayerFactory<Dtype>::createLayer(layer_param));
		}
		layer_names.push_back(layer_param.name());
		LOG_IF(INFO, Dragon::get_root_solver()) << "Create Layer: " << layer_param.name();
		bool need_bp = false;
		//	stuff bottom blobs
		for (int bottom_id = 0; bottom_id < layer_param.bottom_size(); bottom_id++){
			const int blob_id = appendBottom(param, layer_id, bottom_id, &available_blobs, &blob_name_to_idx);
			//	check whether a bottom need back propogation
			need_bp |= blobs_need_backward[blob_id];
		}
		//	stuff top blobs
		for (int top_id = 0; top_id < layer_param.top_size(); top_id++)
			appendTop(param, layer_id, top_id, &available_blobs, &blob_name_to_idx);
		//	auto top blobs
		//	NOT_IMPLEMENTED;
		Layer<Dtype>* layer = layers[layer_id].get();
		//	setup for layer
		if (share_from_root){
			const vector<Blob<Dtype>*> base_top = root_net->top_vecs[layer_id];
			const vector<Blob<Dtype>*> this_top = this->top_vecs[layer_id];
			//	reshape solely after root_net finishing
			for (int top_id = 0; top_id < base_top.size(); top_id++){
				this_top[top_id]->reshapeLike(*base_top[top_id]);
			}
		}
		else layer->setup(bottom_vecs[layer_id], top_vecs[layer_id]);
		LOG_IF(INFO, Dragon::get_root_solver()) << "Setup Layer: " << layer_param.name();
		for (int top_id = 0; top_id < top_vecs[layer_id].size(); top_id++){
			//	extend size to max number of blobs if necessary
			if (blobs_loss_weight.size() <= top_id_vecs[layer_id][top_id])
				blobs_loss_weight.resize(top_id_vecs[layer_id][top_id] + 1, Dtype(0));
			//	store global loss weights from each layer each blob
			blobs_loss_weight[top_id_vecs[layer_id][top_id]] = layer->getLoss(top_id);
			LOG_IF(INFO, Dragon::get_root_solver())
				<< "Top shape: " << top_vecs[layer_id][top_id]->shape_string();
			if (layer->getLoss(top_id)) LOG_IF(INFO, Dragon::get_root_solver())
				<< "	with loss weight " << layer->getLoss(top_id);
			//	sum up for training parameter statistic
			memory_used += top_vecs[layer_id][top_id]->count();
		}
		LOG_IF(INFO, Dragon::get_root_solver())
			<< "Memory required for Data: " << memory_used*sizeof(Dtype);
		const int param_size = layer_param.param_size();
		//	blobs_size will be set after layer->setup()
		const int param_blobs_size = layer->getBlobs().size();
		CHECK_LE(param_size, param_blobs_size)<< "Too many params specify for layer.";
		//	use if do not specify hyperparameter
		//	lr_mult=decay_mult=1.0
		ParamSpec default_hyperparameter;
		for (int param_id = 0; param_id < param_blobs_size; param_id++){
			const ParamSpec* hyperparameter = param_id < param_size ?
				&layer_param.param(param_id) : &default_hyperparameter;
			const bool param_need_bp = hyperparameter->lr_mult() != 0;
			//	check whether a param blob need back propogation [default=true]
			need_bp |= param_need_bp;
			layer->setParamNeedBp(param_id, param_need_bp);
		}
		//	stuff param blobs
		for (int param_id = 0; param_id < param_blobs_size; param_id++)
			appendParam(param, layer_id, param_id);
		//	update param blobs if share others
		shareWeights();
		layer_need_backward.push_back(need_bp);
		//	after checking all bottom blobs and param blobs
		if (need_bp)
			for (int top_id = 0; top_id < top_id_vecs[layer_id].size(); top_id++)
				blobs_need_backward[top_id_vecs[layer_id][top_id]] = true;
	}	//	end layer_id

	set<string> blobs_under_loss, blobs_skip_bp;
	for (int layer_id = layers.size()-1; layer_id >= 0; layer_id--){
		bool layer_contributes_loss = false;
		bool layer_skip_bp = true;
		Layer<Dtype>* layer = layers[layer_id].get();
		for (int top_id = 0; top_id < top_vecs[layer_id].size(); top_id++){
			const string& blob_name = blobs_name[top_id_vecs[layer_id][top_id]];
			if (layer->getLoss(top_id) || blobs_under_loss.count(blob_name))
				layer_contributes_loss = true;
			if (!blobs_skip_bp.count(blob_name)) layer_skip_bp = false;
			//	find any top blobs if affected by loss and do not force to skip bp
			if (layer_contributes_loss&&!layer_skip_bp) break;
		}
		//	optimization trick:	set lr_mult but is not affected by loss
		if (layer_need_backward[layer_id] && layer_skip_bp){
			//	cancel layer
			layer_need_backward[layer_id] = false;
			//	cancel bottom
			for (int bottom_id = 0; bottom_id < bottom_vecs[layer_id].size(); bottom_id++){
				bottoms_need_backward[layer_id][bottom_id] = false;
			}
		}
		//	cancel directly if layer is not affected by loss
		if (!layer_contributes_loss) layer_need_backward[layer_id] = false;
		//	debug info
		if (Dragon::get_root_solver()){
			if (layer_need_backward[layer_id])
				LOG(INFO) << "Layer: " << layer_names[layer_id] << " need back-propogation.";
			else LOG(INFO) << "Layer: " << layer_names[layer_id] << " does not need back-propogation.";
		}
		//	if one top blob affected by loss
		//	all bottom blobs will be affected
		//	regard it as "loss back-affected"
		for (int bottom_id = 0; bottom_id < bottom_vecs[layer_id].size(); bottom_id++){
			const string& blob_name = blobs_name[bottom_id_vecs[layer_id][bottom_id]];
			if (layer_contributes_loss) blobs_under_loss.insert(blob_name);
			else bottoms_need_backward[layer_id][bottom_id] = false;
			//	use for optimization trick : skip all bottom blobs
			if (!bottoms_need_backward[layer_id][bottom_id]) blobs_skip_bp.insert(blob_name);
		}
	}	//	end layer id
	if (param.force_backward()){
		for (int layer_id = 0; layer_id < layers.size(); layer_id++){
			layer_need_backward[layer_id] = true;
			for (int bottom_id = 0; bottom_id < bottom_vecs[layer_id].size(); bottom_id++){
				//	set for bottoms
				bottoms_need_backward[layer_id][bottom_id] =
					bottoms_need_backward[layer_id][bottom_id]||layers[layer_id]->allowForceBackward(bottom_id);
				//	set for blobs
				blobs_need_backward[bottom_id_vecs[layer_id][bottom_id]] =
					blobs_need_backward[bottom_id_vecs[layer_id][bottom_id]]||bottoms_need_backward[layer_id][bottom_id];
			}
			//	set for params
			for (int param_id = 0; param_id < layers[layer_id]->getBlobs().size(); param_id++){
				layers[layer_id]->setParamNeedBp(param_id, true);
			}
		}
	}
	//	move un-used(declare top but not use as bottom) blobs into output blobs
	//	usually contain loss blobs
	for (set<string>::iterator i = available_blobs.begin(); i != available_blobs.end(); i++){
		LOG_IF(INFO, Dragon::get_root_solver())
			<< "Network produces output: " << *i;
		net_output_blobs.push_back(blobs[blob_name_to_idx[*i]].get());
		net_output_blob_indices.push_back(blob_name_to_idx[*i]);
	}
	//	store blob_name -> blob_ids
	blobs_name_idx = blob_name_to_idx;
	//	store layer_name -> layer_id
	for (size_t layer_id = 0; layer_id < layer_names.size(); layer_id++)
		layers_name_idx[layer_names[layer_id]] = layer_id;
	debug_info = param.debug_info();
	LOG_IF(INFO, Dragon::get_root_solver()) << "Network Initializion done.";
}
示例#11
0
Func* FuncEmitter::create(Unit& unit, PreClass* preClass /* = NULL */) const {
  bool isGenerated = isdigit(name->data()[0]) || needsStripInOut(name);

  Attr attrs = this->attrs;
  if (preClass && preClass->attrs() & AttrInterface) {
    attrs |= AttrAbstract;
  }
  if (!RuntimeOption::RepoAuthoritative) {
    if (RuntimeOption::EvalJitEnableRenameFunction) {
      attrs |= AttrInterceptable;
    } else {
      attrs = Attr(attrs & ~AttrInterceptable);
    }
  }
  if (attrs & AttrPersistent && !preClass) {
    if ((RuntimeOption::EvalJitEnableRenameFunction ||
         attrs & AttrInterceptable ||
         (!RuntimeOption::RepoAuthoritative && SystemLib::s_inited))) {
      if (attrs & AttrBuiltin) {
        SystemLib::s_anyNonPersistentBuiltins = true;
      }
      attrs = Attr(attrs & ~AttrPersistent);
    }
  } else {
    assertx(preClass || !(attrs & AttrBuiltin));
  }
  if (!RuntimeOption::RepoAuthoritative) {
    // In non-RepoAuthoritative mode, any function could get a VarEnv because
    // of evalPHPDebugger.
    attrs |= AttrMayUseVV;
  } else if ((attrs & AttrInterceptable) &&
             !name->empty() &&
             !Func::isSpecial(name) &&
             !isClosureBody) {
    // intercepted functions need to pass all args through
    // to the interceptee
    attrs |= AttrMayUseVV;
  }
  if (isVariadic()) {
    attrs |= AttrVariadicParam;
    if (isVariadicByRef()) {
      attrs |= AttrVariadicByRef;
    }
  }

  assertx(!m_pce == !preClass);
  auto f = m_ue.newFunc(this, unit, name, attrs, params.size());

  f->m_isPreFunc = !!preClass;

  bool const needsExtendedSharedData =
    isNative ||
    line2 - line1 >= Func::kSmallDeltaLimit ||
    past - base >= Func::kSmallDeltaLimit ||
    m_numClsRefSlots > 3;

  f->m_shared.reset(
    needsExtendedSharedData
      ? new Func::ExtendedSharedData(preClass, base, past, line1, line2,
                                     top, !containsCalls, docComment)
      : new Func::SharedData(preClass, base, past,
                             line1, line2, top, !containsCalls, docComment)
  );

  f->init(params.size());

  if (auto const ex = f->extShared()) {
    ex->m_hasExtendedSharedData = true;
    ex->m_arFuncPtr = nullptr;
    ex->m_nativeFuncPtr = nullptr;
    ex->m_line2 = line2;
    ex->m_past = past;
    ex->m_returnByValue = false;
    ex->m_isMemoizeWrapper = false;
    ex->m_isMemoizeWrapperLSB = false;
    ex->m_actualNumClsRefSlots = m_numClsRefSlots;
  }

  std::vector<Func::ParamInfo> fParams;
  for (unsigned i = 0; i < params.size(); ++i) {
    Func::ParamInfo pi = params[i];
    if (pi.isVariadic()) {
      pi.builtinType = RuntimeOption::EvalHackArrDVArrs
        ? KindOfVec : KindOfArray;
    }
    f->appendParam(params[i].byRef, pi, fParams);
  }

  auto const originalFullName =
    (!originalFilename ||
     !RuntimeOption::RepoAuthoritative ||
     FileUtil::isAbsolutePath(originalFilename->slice())) ?
    originalFilename :
    makeStaticString(RuntimeOption::SourceRoot +
                     originalFilename->toCppString());

  f->shared()->m_localNames.create(m_localNames);
  f->shared()->m_numLocals = m_numLocals;
  f->shared()->m_numIterators = m_numIterators;
  f->m_maxStackCells = maxStackCells;
  f->shared()->m_staticVars = staticVars;
  f->shared()->m_ehtab = ehtab;
  f->shared()->m_fpitab = fpitab;
  f->shared()->m_isClosureBody = isClosureBody;
  f->shared()->m_isAsync = isAsync;
  f->shared()->m_isGenerator = isGenerator;
  f->shared()->m_isPairGenerator = isPairGenerator;
  f->shared()->m_userAttributes = userAttributes;
  f->shared()->m_retTypeConstraint = retTypeConstraint;
  f->shared()->m_retUserType = retUserType;
  f->shared()->m_originalFilename = originalFullName;
  f->shared()->m_isGenerated = isGenerated;
  f->shared()->m_repoReturnType = repoReturnType;
  f->shared()->m_repoAwaitedReturnType = repoAwaitedReturnType;
  f->shared()->m_isMemoizeWrapper = isMemoizeWrapper;
  f->shared()->m_isMemoizeWrapperLSB = isMemoizeWrapperLSB;
  f->shared()->m_numClsRefSlots = m_numClsRefSlots;

  if (isNative) {
    auto const ex = f->extShared();

    ex->m_hniReturnType = hniReturnType;

    auto const info = getNativeInfo();

    Attr dummy = AttrNone;
    auto nativeAttributes = parseNativeAttributes(dummy);
    Native::getFunctionPointers(
      info,
      nativeAttributes,
      ex->m_arFuncPtr,
      ex->m_nativeFuncPtr
    );
    ex->m_takesNumArgs = !!(nativeAttributes & Native::AttrTakesNumArgs);

    if (ex->m_nativeFuncPtr) {
      if (info.sig.ret == Native::NativeSig::Type::MixedTV) {
        ex->m_returnByValue = true;
      }
      int extra =
        (nativeAttributes & Native::AttrTakesNumArgs ? 1 : 0) +
        (isMethod() ? 1 : 0);
      assertx(info.sig.args.size() == params.size() + extra);
      for (auto i = params.size(); i--; ) {
        switch (info.sig.args[extra + i]) {
          case Native::NativeSig::Type::ObjectArg:
          case Native::NativeSig::Type::StringArg:
          case Native::NativeSig::Type::ArrayArg:
          case Native::NativeSig::Type::ResourceArg:
          case Native::NativeSig::Type::OutputArg:
          case Native::NativeSig::Type::MixedTV:
            fParams[i].nativeArg = true;
            break;
          default:
            break;
        }
      }
    }
  }

  f->finishedEmittingParams(fParams);
  return f;
}
示例#12
0
Func* FuncEmitter::create(Unit& unit, PreClass* preClass /* = NULL */) const {
  bool isGenerated = isdigit(name->data()[0]) ||
    ParserBase::IsClosureName(name->toCppString());

  Attr attrs = this->attrs;
  if (preClass && preClass->attrs() & AttrInterface) {
    attrs |= AttrAbstract;
  }
  if (attrs & AttrPersistent &&
      ((RuntimeOption::EvalJitEnableRenameFunction && !isGenerated) ||
       (!RuntimeOption::RepoAuthoritative && SystemLib::s_inited) ||
       attrs & AttrInterceptable)) {
    if (attrs & AttrBuiltin) {
      SystemLib::s_anyNonPersistentBuiltins = true;
    }
    attrs = Attr(attrs & ~AttrPersistent);
  }
  if (!RuntimeOption::RepoAuthoritative) {
    // In non-RepoAuthoritative mode, any function could get a VarEnv because
    // of evalPHPDebugger.
    attrs |= AttrMayUseVV;
  } else if (RuntimeOption::EvalJitEnableRenameFunction &&
      !name->empty() &&
      !Func::isSpecial(name) &&
      !isClosureBody) {
    // intercepted functions need to pass all args through
    // to the interceptee
    attrs |= AttrMayUseVV;
  }
  if (isVariadic()) { attrs |= AttrVariadicParam; }

  if (!containsCalls) { attrs |= AttrPhpLeafFn; }

  assert(!m_pce == !preClass);
  auto f = m_ue.newFunc(this, unit, name, attrs, params.size());

  f->m_isPreFunc = !!preClass;

  bool const needsExtendedSharedData =
    m_info ||
    m_builtinFuncPtr ||
    m_nativeFuncPtr ||
    (attrs & AttrNative) ||
    line2 - line1 >= Func::kSmallDeltaLimit ||
    past - base >= Func::kSmallDeltaLimit;

  f->m_shared.reset(
    needsExtendedSharedData
      ? new Func::ExtendedSharedData(preClass, base, past, line1, line2,
                                     top, docComment)
      : new Func::SharedData(preClass, base, past,
                             line1, line2, top, docComment)
  );

  f->init(params.size());

  if (auto const ex = f->extShared()) {
    ex->m_hasExtendedSharedData = true;
    ex->m_builtinFuncPtr = m_builtinFuncPtr;
    ex->m_nativeFuncPtr = m_nativeFuncPtr;
    ex->m_info = m_info;
    ex->m_line2 = line2;
    ex->m_past = past;
    ex->m_returnByValue = false;
  }

  std::vector<Func::ParamInfo> fParams;
  for (unsigned i = 0; i < params.size(); ++i) {
    Func::ParamInfo pi = params[i];
    if (pi.isVariadic()) {
      pi.builtinType = KindOfArray;
    }
    f->appendParam(params[i].byRef, pi, fParams);
  }

  f->shared()->m_returnType = returnType;
  f->shared()->m_localNames.create(m_localNames);
  f->shared()->m_numLocals = m_numLocals;
  f->shared()->m_numIterators = m_numIterators;
  f->m_maxStackCells = maxStackCells;
  f->shared()->m_staticVars = staticVars;
  f->shared()->m_ehtab = toFixed(ehtab);
  f->shared()->m_fpitab = fpitab;
  f->shared()->m_isClosureBody = isClosureBody;
  f->shared()->m_isAsync = isAsync;
  f->shared()->m_isGenerator = isGenerator;
  f->shared()->m_isPairGenerator = isPairGenerator;
  f->shared()->m_userAttributes = userAttributes;
  f->shared()->m_retTypeConstraint = retTypeConstraint;
  f->shared()->m_retUserType = retUserType;
  f->shared()->m_originalFilename = originalFilename;
  f->shared()->m_isGenerated = isGenerated;

  if (attrs & AttrNative) {
    auto const ex = f->extShared();

    auto const& info = Native::GetBuiltinFunction(
      name,
      m_pce ? m_pce->name() : nullptr,
      f->isStatic()
    );

    Attr dummy = AttrNone;
    auto nativeAttributes = parseNativeAttributes(dummy);
    Native::getFunctionPointers(
      info,
      nativeAttributes,
      ex->m_builtinFuncPtr,
      ex->m_nativeFuncPtr
    );

    if (ex->m_nativeFuncPtr &&
        !(nativeAttributes & Native::AttrZendCompat)) {
      if (info.sig.ret == Native::NativeSig::Type::MixedTV) {
        ex->m_returnByValue = true;
      }
      int extra =
        (attrs & AttrNumArgs ? 1 : 0) +
        (isMethod() ? 1 : 0);
      assert(info.sig.args.size() == params.size() + extra);
      for (auto i = params.size(); i--; ) {
        switch (info.sig.args[extra + i]) {
          case Native::NativeSig::Type::ObjectArg:
          case Native::NativeSig::Type::StringArg:
          case Native::NativeSig::Type::ArrayArg:
          case Native::NativeSig::Type::ResourceArg:
          case Native::NativeSig::Type::OutputArg:
          case Native::NativeSig::Type::MixedTV:
            fParams[i].nativeArg = true;
            break;
          default:
            break;
        }
      }
    }
  }

  f->finishedEmittingParams(fParams);
  return f;
}
示例#13
0
Func* FuncEmitter::create(Unit& unit, PreClass* preClass /* = NULL */) const {
  bool isGenerated = isdigit(name->data()[0]) ||
    ParserBase::IsClosureName(name->toCppString());

  Attr attrs = this->attrs;
  if (preClass && preClass->attrs() & AttrInterface) {
    attrs |= AttrAbstract;
  }
  if (attrs & AttrPersistent &&
      ((RuntimeOption::EvalJitEnableRenameFunction && !isGenerated) ||
       (!RuntimeOption::RepoAuthoritative && SystemLib::s_inited) ||
       attrs & AttrInterceptable)) {
    if (attrs & AttrBuiltin) {
      SystemLib::s_anyNonPersistentBuiltins = true;
    }
    attrs = Attr(attrs & ~AttrPersistent);
  }
  if (!RuntimeOption::RepoAuthoritative) {
    // In non-RepoAuthoritative mode, any function could get a VarEnv because
    // of evalPHPDebugger.
    attrs |= AttrMayUseVV;
  } else if (RuntimeOption::EvalJitEnableRenameFunction &&
      !name->empty() &&
      !Func::isSpecial(name) &&
      !isClosureBody) {
    // intercepted functions need to pass all args through
    // to the interceptee
    attrs |= AttrMayUseVV;
  }
  if (isVariadic()) { attrs |= AttrVariadicParam; }

  if (!containsCalls) { attrs |= AttrPhpLeafFn; }

  assert(!m_pce == !preClass);
  auto f = m_ue.newFunc(this, unit, name, attrs, params.size());

  f->m_isPreFunc = !!preClass;

  bool const needsExtendedSharedData =
    m_info ||
    m_builtinFuncPtr ||
    m_nativeFuncPtr ||
    (attrs & AttrNative) ||
    line2 - line1 >= Func::kSmallDeltaLimit ||
    past - base >= Func::kSmallDeltaLimit;

  f->m_shared.reset(
    needsExtendedSharedData
      ? new Func::ExtendedSharedData(preClass, base, past, line1, line2,
                                     top, docComment)
      : new Func::SharedData(preClass, base, past,
                             line1, line2, top, docComment)
  );

  f->init(params.size());

  if (auto const ex = f->extShared()) {
    ex->m_hasExtendedSharedData = true;
    ex->m_builtinFuncPtr = m_builtinFuncPtr;
    ex->m_nativeFuncPtr = m_nativeFuncPtr;
    ex->m_info = m_info;
    ex->m_line2 = line2;
    ex->m_past = past;
  }

  std::vector<Func::ParamInfo> fParams;
  bool usesDoubles = false, variadic = false;
  for (unsigned i = 0; i < params.size(); ++i) {
    Func::ParamInfo pi = params[i];
    if (pi.builtinType == KindOfDouble) usesDoubles = true;
    if (pi.isVariadic()) variadic = true;
    f->appendParam(params[i].byRef, pi, fParams);
  }

  f->shared()->m_returnType = returnType;
  f->shared()->m_localNames.create(m_localNames);
  f->shared()->m_numLocals = m_numLocals;
  f->shared()->m_numIterators = m_numIterators;
  f->m_maxStackCells = maxStackCells;
  f->shared()->m_staticVars = staticVars;
  f->shared()->m_ehtab = toFixed(ehtab);
  f->shared()->m_fpitab = fpitab;
  f->shared()->m_isClosureBody = isClosureBody;
  f->shared()->m_isAsync = isAsync;
  f->shared()->m_isGenerator = isGenerator;
  f->shared()->m_isPairGenerator = isPairGenerator;
  f->shared()->m_userAttributes = userAttributes;
  f->shared()->m_retTypeConstraint = retTypeConstraint;
  f->shared()->m_retUserType = retUserType;
  f->shared()->m_originalFilename = originalFilename;
  f->shared()->m_isGenerated = isGenerated;

  f->finishedEmittingParams(fParams);

  if (attrs & AttrNative) {
    auto const ex = f->extShared();

    auto const& info = Native::GetBuiltinFunction(
      name,
      m_pce ? m_pce->name() : nullptr,
      f->isStatic()
    );

    auto const nif = info.ptr;
    if (nif) {
      Attr dummy = AttrNone;
      int nativeAttrs = parseNativeAttributes(dummy);
      if (nativeAttrs & Native::AttrZendCompat) {
        ex->m_nativeFuncPtr = nif;
        ex->m_builtinFuncPtr = zend_wrap_func;
      } else {
        if (parseNativeAttributes(dummy) & Native::AttrActRec) {
          ex->m_builtinFuncPtr = nif;
          ex->m_nativeFuncPtr = nullptr;
        } else {
          ex->m_nativeFuncPtr = nif;
          ex->m_builtinFuncPtr =
            Native::getWrapper(m_pce, usesDoubles, variadic);
        }
      }
    } else {
      ex->m_builtinFuncPtr = Native::unimplementedWrapper;
    }
  }

  return f;
}