Skip to content

Commit 66d4afc

Browse files
committed
Improve call stack performance.
1 parent 5d56885 commit 66d4afc

File tree

10 files changed

+136
-25
lines changed

10 files changed

+136
-25
lines changed

jphp-runtime/package.php.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11

22
name: jphp-runtime
3-
version: 1.1.1
3+
version: 1.1.2
44
description: Runtime for JPHP + Standard library.
55

66
plugins: [Doc, Hub]

jphp-runtime/src/php/runtime/env/CallStack.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import php.runtime.Memory;
44
import php.runtime.lang.IObject;
5+
import php.runtime.reflection.ClassEntity;
56
import php.runtime.reflection.ModuleEntity;
67

78
public class CallStack {
@@ -140,4 +141,17 @@ public ModuleEntity module(int depth) {
140141
public TraceInfo trace(int systemOffsetStackTrace){
141142
return new TraceInfo(Thread.currentThread().getStackTrace()[systemOffsetStackTrace]);
142143
}
144+
145+
public CallStackItem push(TraceInfo trace, IObject iObject, Memory[] args, String methodName, ClassEntity clazz, String staticClass) {
146+
CallStackItem push = push(new CallStackItem(trace, iObject, args, methodName, clazz.getName(), staticClass));
147+
push.classEntity = clazz;
148+
return push;
149+
}
150+
151+
public CallStackItem push(TraceInfo trace, IObject iObject, Memory[] args, String originMethodName, ClassEntity clazz, ClassEntity classEntity) {
152+
CallStackItem stackItem = push(new CallStackItem(trace, null, args, originMethodName, clazz.getName(), classEntity.getName()));
153+
stackItem.classEntity = clazz;
154+
stackItem.staticClassEntity = classEntity;
155+
return stackItem;
156+
}
143157
}

jphp-runtime/src/php/runtime/env/Environment.java

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,21 @@ public TraceInfo trace() {
442442
return getCallStack().trace();
443443
}
444444

445+
public TraceInfo traceCloned() {
446+
TraceInfo trace = getCallStack().trace();
447+
if (trace != null) {
448+
try {
449+
TraceInfo clone = trace.clone();
450+
clone.setCallCache(null);
451+
return clone;
452+
} catch (CloneNotSupportedException e) {
453+
return null;
454+
}
455+
}
456+
457+
return null;
458+
}
459+
445460
public TraceInfo trace(int systemOffsetStackTrace) {
446461
return getCallStack().trace(systemOffsetStackTrace);
447462
}
@@ -1703,7 +1718,7 @@ public Memory invokeMethod(TraceInfo trace, IObject object, String name, Memory.
17031718
}
17041719

17051720
public Memory invokeMethod(IObject object, String name, Memory... args) throws Throwable {
1706-
return ObjectInvokeHelper.invokeMethod(new ObjectMemory(object), name, name.toLowerCase(), this, trace(), args);
1721+
return ObjectInvokeHelper.invokeMethod(new ObjectMemory(object), name, name.toLowerCase(), this, traceCloned(), args);
17071722
}
17081723

17091724
public Memory invokeMethodNoThrow(IObject object, String name, Memory... args) {
@@ -1724,7 +1739,7 @@ public Memory invokeMethod(TraceInfo trace, Memory object, String name, Memory..
17241739
}
17251740

17261741
public Memory invokeMethod(Memory object, String name, Memory... args) throws Throwable {
1727-
return ObjectInvokeHelper.invokeMethod(object, name, name.toLowerCase(), this, trace(), args);
1742+
return ObjectInvokeHelper.invokeMethod(object, name, name.toLowerCase(), this, traceCloned(), args);
17281743
}
17291744

17301745
public void assignProperty(IObject object, String property, Memory value) throws Throwable {

jphp-runtime/src/php/runtime/env/TraceInfo.java

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import java.io.File;
44

5-
public class TraceInfo {
5+
public class TraceInfo implements Cloneable {
66
public final static TraceInfo UNKNOWN = new TraceInfo("Unknown", -1, -1);
77

88
private Context context;
@@ -15,6 +15,8 @@ public class TraceInfo {
1515

1616
private String fileName;
1717

18+
private TraceInfoCallCache callCache;
19+
1820
public TraceInfo(StackTraceElement element) {
1921
this.fileName = element.getFileName();
2022
this.startLine = element.getLineNumber() + 1;
@@ -48,6 +50,18 @@ public static TraceInfo valueOf(String fileName, long startLine, long startPosit
4850
return new TraceInfo(fileName, (int) startLine, (int) startPosition);
4951
}
5052

53+
public TraceInfoCallCache getCallCache() {
54+
if (this == UNKNOWN) return null;
55+
56+
return callCache;
57+
}
58+
59+
public void setCallCache(TraceInfoCallCache callCache) {
60+
if (this == UNKNOWN) return;
61+
62+
this.callCache = callCache;
63+
}
64+
5165
public Context getContext() {
5266
if (context == null){
5367
context = new Context(null, new File(fileName));
@@ -82,4 +96,9 @@ public int getEndPosition() {
8296
public boolean isUnknown(){
8397
return this == UNKNOWN;
8498
}
99+
100+
@Override
101+
protected TraceInfo clone() throws CloneNotSupportedException {
102+
return (TraceInfo) super.clone();
103+
}
85104
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package php.runtime.env;
2+
3+
import php.runtime.reflection.MethodEntity;
4+
import php.runtime.reflection.support.AbstractFunctionEntity;
5+
6+
public class TraceInfoCallCache {
7+
public Object self;
8+
public AbstractFunctionEntity callEntity;
9+
10+
public TraceInfoCallCache() {
11+
}
12+
13+
public TraceInfoCallCache(Object self, AbstractFunctionEntity callEntity) {
14+
this.self = self;
15+
this.callEntity = callEntity;
16+
}
17+
}

jphp-runtime/src/php/runtime/invoke/InvokeHelper.java

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
import php.runtime.common.Function;
99
import php.runtime.common.HintType;
1010
import php.runtime.common.Messages;
11+
import php.runtime.env.CallStack;
12+
import php.runtime.env.CallStackItem;
1113
import php.runtime.env.Environment;
1214
import php.runtime.env.TraceInfo;
1315
import php.runtime.exceptions.FatalException;
@@ -235,15 +237,20 @@ public static Memory call(Environment env, TraceInfo trace, FunctionEntity funct
235237
return result;
236238
}
237239

238-
if (trace != null && function.isUsesStackTrace())
239-
env.pushCall(trace, null, args, function.getName(), null, null);
240+
CallStack callStack = trace != null && function.isUsesStackTrace() ? env.getCallStack() : null;
241+
242+
if (callStack != null) {
243+
callStack.push(trace, null, args, function.getName(), (String) null, (String) null);
244+
}
240245

241246
try {
242247
result = function.invoke(env, trace, passed);
243248
} finally {
244-
if (trace != null && function.isUsesStackTrace())
245-
env.popCall();
249+
if (callStack != null) {
250+
callStack.pop();
251+
}
246252
}
253+
247254
return result;
248255
}
249256

@@ -369,14 +376,18 @@ public static Memory callStatic(Environment env, TraceInfo trace,
369376
return result;
370377
}
371378

379+
CallStack callStack = trace != null && method.isUsesStackTrace() ? env.getCallStack() : null;
380+
372381
try {
373-
if (trace != null)
374-
env.pushCallEx(trace, null, args, originMethodName, method.getClazz(), classEntity);
382+
if (callStack != null) {
383+
callStack.push(trace, (IObject) null, args, originMethodName, method.getClazz(), classEntity);
384+
}
375385

376386
return method.invokeStatic(env, trace, passed);
377387
} finally {
378-
if (trace != null)
379-
env.popCall();
388+
if (callStack != null) {
389+
callStack.pop();
390+
}
380391
}
381392
}
382393

@@ -410,15 +421,18 @@ public static Memory callStatic(Environment env, TraceInfo trace,
410421
env, args, method.getParameters(), originClassName, originMethodName, staticClass, trace
411422
);
412423

424+
CallStack callStack = trace != null && method.isUsesStackTrace() ? env.getCallStack() : null;
425+
413426
try {
414-
if (trace != null && method.isUsesStackTrace()) {
415-
env.pushCallEx(trace, null, passed, originMethodName, method.getClazz(), staticClazz);
427+
if (callStack != null) {
428+
callStack.push(trace, null, passed, originMethodName, method.getClazz(), staticClazz);
416429
}
417430

418431
return method.invokeStatic(env, passed);
419432
} finally {
420-
if (trace != null && method.isUsesStackTrace())
421-
env.popCall();
433+
if (callStack != null) {
434+
callStack.pop();
435+
}
422436
}
423437
}
424438

jphp-runtime/src/php/runtime/invoke/ObjectInvokeHelper.java

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,11 @@
33
import php.runtime.Memory;
44
import php.runtime.common.Messages;
55
import php.runtime.common.Modifier;
6+
import php.runtime.env.CallStack;
7+
import php.runtime.env.CallStackItem;
68
import php.runtime.env.Environment;
79
import php.runtime.env.TraceInfo;
10+
import php.runtime.env.TraceInfoCallCache;
811
import php.runtime.exceptions.CriticalException;
912
import php.runtime.exceptions.support.ErrorType;
1013
import php.runtime.invoke.cache.ConstantCallCache;
@@ -143,6 +146,22 @@ public static Memory invokeMethod(Memory object, String methodName, String metho
143146
method = clazz.methodMagicInvoke;
144147
} else {
145148
method = clazz.findMethod(methodLowerName);
149+
/*TraceInfoCallCache callCache = trace == null ? null : trace.getCallCache();
150+
151+
if (callCache != null && callCache.self == clazz && callCache.callEntity != null) {
152+
method = (MethodEntity) callCache.callEntity;
153+
} else {
154+
method = clazz.findMethod(methodLowerName);
155+
if (trace != null && !trace.isUnknown()) {
156+
if (callCache == null) {
157+
callCache = new TraceInfoCallCache();
158+
}
159+
160+
callCache.self = clazz;
161+
callCache.callEntity = method;
162+
trace.setCallCache(callCache);
163+
}
164+
}*/
146165

147166
if (method != null && method.isContextDepends()) {
148167
ClassEntity context = env.getLastClassOnStack();
@@ -195,25 +214,31 @@ public static Memory invokeMethod(Memory object, String methodName, String metho
195214
return result;
196215
}
197216

217+
CallStack callStack = (trace == null || !method.isUsesStackTrace()) ? null : env.getCallStack();
218+
198219
try {
199-
if (trace != null) {
220+
if (callStack != null) {
200221
String staticClass = className;
201222

202223
if (iObject instanceof Closure) {
203224
staticClass = ((Closure) iObject).getScope();
204225
}
205226

206227
if (clazz.isHiddenInCallStack()) {
207-
env.pushCall(trace, iObject, args, methodName, staticClass, staticClass);
228+
callStack.push(trace, iObject, args, methodName, staticClass, staticClass);
229+
//env.pushCall(trace, iObject, args, methodName, staticClass, staticClass);
208230

209231
if (doublePop) {
210-
env.pushCall(trace, iObject, passed, method.getName(), staticClass, staticClass);
232+
callStack.push(trace, iObject, passed, method.getName(), staticClass, staticClass);
233+
//env.pushCall(trace, iObject, passed, method.getName(), staticClass, staticClass);
211234
}
212235
} else {
213-
env.pushCallEx(trace, iObject, args, methodName, method.getClazz(), staticClass);
236+
callStack.push(trace, iObject, args, methodName, method.getClazz(), staticClass);
237+
//env.pushCallEx(trace, iObject, args, methodName, method.getClazz(), staticClass);
214238

215239
if (doublePop) {
216-
env.pushCallEx(trace, iObject, passed, method.getName(), method.getClazz(), staticClass);
240+
callStack.push(trace, iObject, passed, method.getName(), method.getClazz(), staticClass);
241+
//env.pushCallEx(trace, iObject, passed, method.getName(), method.getClazz(), staticClass);
217242
}
218243
}
219244
}
@@ -222,11 +247,13 @@ public static Memory invokeMethod(Memory object, String methodName, String metho
222247
} catch (NoClassDefFoundError e) {
223248
throw new CriticalException("Unable to call method " + className + "::" + methodName + "(), " + e.getMessage());
224249
} finally {
225-
if (trace != null) {
226-
env.popCall();
250+
if (callStack != null) {
251+
callStack.pop();
252+
//env.popCall();
227253

228254
if (doublePop) {
229-
env.popCall();
255+
callStack.pop();
256+
//env.popCall();
230257
}
231258
}
232259
}

jphp-runtime/src/php/runtime/reflection/CompileMethodEntity.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@
2525
public class CompileMethodEntity extends MethodEntity {
2626
protected CompileMethod function;
2727

28+
{
29+
setUsesStackTrace(true);
30+
}
31+
2832
public CompileMethodEntity(Extension extension) {
2933
super((Context) null);
3034

jphp-runtime/src/php/runtime/reflection/FunctionEntity.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ public Closure getClosure(Environment env) {
116116
closureEntity1.setReturnReference(this.isReturnReference());
117117

118118
MethodEntity m = new MethodEntity(this);
119+
m.setUsesStackTrace(true);
119120
m.setClazz(closureEntity1);
120121
m.setName("__invoke");
121122
closureEntity1.addMethod(m, null);

packager/src-php/packager/Package.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,7 @@ static public function readPackage($source, array $info = []): Package
323323
try {
324324
$data = $stream->parseAs('yaml');
325325

326-
return new Package($data, $info);
326+
return new Package((array) $data, $info);
327327
} finally {
328328
$stream->close();
329329
}

0 commit comments

Comments
 (0)