difftreelog
perf build stacktrace only on unwind
in: master
2 files changed
crates/jrsonnet-evaluator/src/evaluate.rsdiffbeforeafterboth658 Num(v) => Val::new_checked_num(*v)?,658 Num(v) => Val::new_checked_num(*v)?,659 BinaryOp(v1, o, v2) => evaluate_binary_op_special(context, &v1, *o, &v2)?,659 BinaryOp(v1, o, v2) => evaluate_binary_op_special(context, &v1, *o, &v2)?,660 UnaryOp(o, v) => evaluate_unary_op(*o, &evaluate(context, v)?)?,660 UnaryOp(o, v) => evaluate_unary_op(*o, &evaluate(context, v)?)?,661 Var(name) => push(loc, "var", || {661 Var(name) => push(662 loc,663 || "var".to_owned(),662 Ok(Val::Lazy(context.binding(name.clone())?).unwrap_if_lazy()?)664 || Ok(Val::Lazy(context.binding(name.clone())?).unwrap_if_lazy()?),663 })?,665 )?,664 Index(LocExpr(v, _), index) if matches!(&**v, Expr::Literal(LiteralType::Super)) => {666 Index(LocExpr(v, _), index) if matches!(&**v, Expr::Literal(LiteralType::Super)) => {665 let name = evaluate(context.clone(), index)?.try_cast_str("object index")?;667 let name = evaluate(context.clone(), index)?.try_cast_str("object index")?;666 context668 context771 AssertExpr(AssertStmt(value, msg), returned) => {773 AssertExpr(AssertStmt(value, msg), returned) => {772 let assertion_result = push(&value.1, "assertion condition", || {774 let assertion_result = push(775 &value.1,776 || "assertion condition".to_owned(),777 || {773 evaluate(context.clone(), &value)?778 evaluate(context.clone(), &value)?774 .try_cast_bool("assertion condition should be boolean")779 .try_cast_bool("assertion condition should be boolean")775 })?;780 },781 )?;776 if assertion_result {782 if assertion_result {777 evaluate(context, returned)?783 evaluate(context, returned)?781 create_error_result(crate::Error::AssertionFailed(Val::Null))?787 create_error_result(crate::Error::AssertionFailed(Val::Null))?782 }788 }783 }789 }784 Error(e) => create_error_result(crate::Error::RuntimeError(790 Error(e) => push(791 &loc,792 || "error statement".to_owned(),793 || {794 create_error_result(crate::Error::RuntimeError(785 evaluate(context, e)?.try_cast_str("error text should be string")?,795 evaluate(context, e)?.try_cast_str("error text should be string")?,786 ))?,796 ))?797 },798 )?,787 IfElse {799 IfElse {788 cond,800 cond,789 cond_then,801 cond_then,crates/jrsonnet-evaluator/src/lib.rsdiffbeforeafterboth727273#[derive(Default)]73#[derive(Default)]74struct EvaluationData {74struct EvaluationData {75 /// Used for stack-overflows and stacktraces75 /// Used for stack overflow detection, stacktrace is now populated on unwind76 stack: Vec<StackTraceElement>,76 stack_depth: usize,77 /// Contains file source codes and evaluated results for imports and pretty77 /// Contains file source codes and evaluated results for imports and pretty78 /// printing stacktraces78 /// printing stacktraces79 files: HashMap<Rc<PathBuf>, FileData>,79 files: HashMap<Rc<PathBuf>, FileData>,103}103}104pub(crate) fn push<T>(104pub(crate) fn push<T>(105 e: &Option<ExprLocation>,105 e: &Option<ExprLocation>,106 comment: &str,106 frame_desc: impl FnOnce() -> String,107 f: impl FnOnce() -> Result<T>,107 f: impl FnOnce() -> Result<T>,108) -> Result<T> {108) -> Result<T> {109 if e.is_some() {109 if let Some(v) = e {110 with_state(|s| s.push(e.clone().unwrap(), comment.to_owned(), f))110 with_state(|s| s.push(&v, frame_desc, f))111 } else {111 } else {112 f()112 f()113 }113 }332 /// Executes code, creating new stack frame332 /// Executes code, creating new stack frame333 pub fn push<T>(333 pub fn push<T>(334 &self,334 &self,335 e: ExprLocation,335 e: &ExprLocation,336 comment: String,336 frame_desc: impl FnOnce() -> String,337 f: impl FnOnce() -> Result<T>,337 f: impl FnOnce() -> Result<T>,338 ) -> Result<T> {338 ) -> Result<T> {339 {339 {340 let mut data = self.data_mut();340 let mut data = self.data_mut();341 let stack = &mut data.stack;341 let stack_depth = &mut data.stack_depth;342 if stack.len() > self.settings().max_stack_frames {342 if *stack_depth > self.settings().max_stack_frames {343 // Error creation uses data, so i drop guard here343 // Error creation uses data, so i drop guard here344 drop(data);344 drop(data);345 return Err(self.error(Error::StackOverflow));345 return Err(self.error(Error::StackOverflow));346 } else {346 } else {347 stack.push(StackTraceElement(e, comment));347 *stack_depth+=1;348 }348 }349 }349 }350 let result = f();350 let result = f();351 self.data_mut().stack.pop();351 self.data_mut().stack_depth -= 1;352 if let Err(mut err) = result {353 (err.1).0.push(StackTraceElement(e.clone(), frame_desc()));354 return Err(err);355 }352 result356 result353 }357 }354355 /// Returns current stack trace356 pub fn stack_trace(&self) -> StackTrace {357 StackTrace(358 self.data()359 .stack360 .iter()361 .rev()362 .take(self.settings().max_stack_trace_size)363 .cloned()364 .collect(),365 )366 }367358368 /// Creates error with stack trace359 /// Creates error with stack trace369 pub fn error(&self, err: Error) -> LocError {360 pub fn error(&self, err: Error) -> LocError {370 LocError(err, self.stack_trace())361 LocError(err, StackTrace(vec![]))371 }362 }372363373 /// Runs passed function in state (required, if function needs to modify stack trace)364 /// Runs passed function in state (required, if function needs to modify stack trace)396 #[test]387 #[test]397 fn eval_state_stacktrace() {388 fn eval_state_stacktrace() {398 let state = EvaluationState::default();389 let state = EvaluationState::default();390 state.run_in_state(||{399 state391 state400 .push(392 .push(401 ExprLocation(Rc::new(PathBuf::from("test1.jsonnet")), 10, 20),393 &ExprLocation(Rc::new(PathBuf::from("test1.jsonnet")), 10, 20),402 "outer".to_owned(),394 || "outer".to_owned(),403 || {395 || {404 state.push(396 state.push(405 ExprLocation(Rc::new(PathBuf::from("test2.jsonnet")), 30, 40),397 &ExprLocation(Rc::new(PathBuf::from("test2.jsonnet")), 30, 40),406 "inner".to_owned(),398 || "inner".to_owned(),407 || {399 || {408 Ok(())400 Err(create_error(crate::error::Error::RuntimeError("".into())))409 },401 },410 )?;402 )?;411 Ok(())403 Ok(())412 },404 },413 )405 )406 .unwrap();414 .unwrap();407 });415 }408 }416409417 #[test]410 #[test]