aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDrahflow <drahflow@gmx.de>2015-06-19 15:49:25 +0200
committerDrahflow <drahflow@gmx.de>2015-06-19 15:49:25 +0200
commit350c441e9b6c1a5fc095263e7ddf8be9918c626c (patch)
tree91e9e5f80cef7490c859cf011004ab5d945cb2c2
parent779fb09b603b83440685ae249557c677055031ba (diff)
Forward function objects to jump pad targets
... and fix really ugly memory bugs occuring because some code referenced function objects not the code objects it was calling
-rw-r--r--TODO2
-rw-r--r--compiler/elymasAsmLib.ey25
-rw-r--r--compiler/elymasGlobal.ey18
-rw-r--r--elymas/lib/sys/opt.ey21
4 files changed, 54 insertions, 12 deletions
diff --git a/TODO b/TODO
index 20ae1a5..b8dee38 100644
--- a/TODO
+++ b/TODO
@@ -1,6 +1,6 @@
* apply the trace extractor to non-tail situations
-* implement the GC-based function opcode forwarding
* forward scope-cannot-escape information
+* inline trivial functions when optimizer generates ... /rax :movqImmReg /rax :callqReg sequence
* utf8
* regex substitution
* asm-based regex engine
diff --git a/compiler/elymasAsmLib.ey b/compiler/elymasAsmLib.ey
index 42d6ecb..4d51ce5 100644
--- a/compiler/elymasAsmLib.ey
+++ b/compiler/elymasAsmLib.ey
@@ -664,6 +664,7 @@
/r10 :pushqReg
/r11 :pushqReg
/r12 :pushqReg
+ /r13 :pushqReg
/r8 :movqImmOOBReg HEAPBASE # constant through mark
/r9 :movqImmOOBReg BLOCKBASE # constant through mark
@@ -693,12 +694,13 @@
/resetMarkLoop :loopLbl8
@noResetNecessary
- # start from current scope and mark all reachable blocks
- /r14 /rdi :movqRegReg
+ # start from current coroutine and mark all reachable blocks
+ /r13 /rdi :movqRegReg # r13 must be checked first because we use it in markObject
+ /r13 /r13 :xorqRegReg
/markObject :callqLbl32
- # start from current coroutine and mark all reachable blocks
- /r13 /rdi :movqRegReg
+ # start from current scope and mark all reachable blocks
+ /r14 /rdi :movqRegReg
/markObject :callqLbl32
# start from stack and mark all reachable blocks
@@ -760,6 +762,7 @@
/freeLoop :loopLbl8
@noFreeNecessary
+ /r13 :popqReg
/r12 :popqReg
/r11 :popqReg
/r10 :popqReg
@@ -984,6 +987,7 @@
16 /rsi /rdi :movqMemDisp8Reg
/markObject :callqLbl32
24 /rsi /rdi :movqMemDisp8Reg
+ /rsi /r13 :movqRegReg # optimistically inform the mark on the code object of our location
/rsi :popqReg
/markObject :jmpLbl32
@@ -1028,7 +1032,18 @@
/markFunctionCodeFull :jnzLbl8
1 [ /rax :jmpqReg ] * 27 /rdi :cmpbImmMemDisp8
/markFunctionCodeFull :jnzLbl8
- # TODO: This would be good moment to forward the incoming reference (which is on the stack somewhere), actually
+
+ /r13 /r13 :testqRegReg # check whether r13 contains something (a function object)
+ /noRewritePossible :jzLbl8
+ 24 /r13 /rdi :cmpqMemDisp8Reg # ... which points to the forwarding function code object
+ /noRewritePossible :jnzLbl8
+
+ 18 /rdi /rdi :movqMemDisp8Reg
+ 16 /rdi :subqImm8Reg
+ /rdi 24 /r13 :movqRegMemDisp8 # if so, rewrite the originating function object while we are at it
+ /markObject :jmpLbl32
+
+ @noRewritePossible
18 /rdi /rdi :movqMemDisp8Reg
16 /rdi :subqImm8Reg
/markObject :jmpLbl32
diff --git a/compiler/elymasGlobal.ey b/compiler/elymasGlobal.ey
index 5d9f8f9..b35aa7a 100644
--- a/compiler/elymasGlobal.ey
+++ b/compiler/elymasGlobal.ey
@@ -1482,7 +1482,9 @@
:retn
] ::loadToRdi
- /rdx 0 /rbp :movqRegMemDisp8 # save object reference
+ /rcx 0 /rbp :movqRegMemDisp8 # save scope reference
+ 16 /rbx :subqImm8Reg
+ /rbx 8 /rbp :movqRegMemDisp8 # ... and code reference (in case the function object is ever updated)
8 /r15 /rdi :movqMemDisp8Reg
16 /rdi :addqImm8Reg
@@ -1515,7 +1517,8 @@
[
/rax :jmpqReg
] ::loadToRdi
- /rdx 0 /rbp :movqRegMemDisp8 # save the address for the GC
+ 16 /rcx :subqImm8Reg
+ /rcx 0 /rbp :movqRegMemDisp8 # save code address for the GC
8 /r15 /rdi :movqMemDisp8Reg
16 /rdi :addqImm8Reg
@@ -1527,20 +1530,24 @@
@patchConstantPassive
8 /r15 /rdi :movqMemDisp8Reg
- # TODO: could reset string reference here
+ 8 /rdi /rbp :movqMemDisp8Reg
+ 16 1 /rbp /rdi /rbp :leaqMemIndexScaleDisp8Reg
16 /rdi :addqImm8Reg
[
/rbx :popqReg
/rax :movqImmOOBReg
] ::loadToRdi
- /rdi :popqMem
+ /rdx :popqReg
+ /rdx /rdi :movqRegMem
8 /rdi :addqImm8Reg
[
/rax :pushqReg
/rbx :jmpqReg
] ::loadToRdi
+ /rdx 0 /rbp :movqRegMemDisp8 # save constant address for the GC
+
8 /r15 /rdi :movqMemDisp8Reg
16 /rdi :addqImm8Reg
@@ -1825,7 +1832,8 @@
/rsi /rdi :movqRegMem
/rsi 0 /rbp :movqRegMemDisp8
8 /rdi :addqImm8Reg
- 8 /rbp :addqImm8Reg
+ 16 /rbp :addqImm8Reg # we only save 1 reference here, but some cases need 2 after patching
+ 0 8 neg /rbp :andqImm8MemDisp8
[
/rax :pushqReg
diff --git a/elymas/lib/sys/opt.ey b/elymas/lib/sys/opt.ey
index c15d0d5..009b6fa 100644
--- a/elymas/lib/sys/opt.ey
+++ b/elymas/lib/sys/opt.ey
@@ -360,6 +360,9 @@
] { | ::rawCodeAddress } [ 0 ] [ 0 ] '' * ==:STATICDEFININGFUNCTIONS
{ ==o ==executingScope
+ [ ] ==fragileReferences # things the GC should leave alone while we are working on it
+ { [ -01 ] fragileReferences cat =fragileReferences } /protectReference deffst
+
0 ==containsScopeModifications
{ _ ==logic
logic { ==entry 0 entry * ==action
@@ -1670,9 +1673,11 @@
executedObject sys .capturedScope { ==scope
[ NOP ] i 1 sub logic =[]
[ CALLSCOPED executedObject ::rawCodeAddress scope ::rawAddress ] i logic =[]
+ executedObject ::rawCodeAddress 16 sub ::rawObject protectReference
} {
[ NOP ] i 1 sub logic =[]
[ CALL executedObject ::rawCodeAddress ] i logic =[]
+ executedObject ::rawCodeAddress 16 sub ::rawObject protectReference
} ? *
} ? *
}
@@ -1721,6 +1726,7 @@
} {
[ NOP ] i 1 sub logic =[]
[ RAWCONSTREP executedObject ::rawCodeAddress ] i logic =[]
+ executedObject ::rawCodeAddress 16 sub ::rawObject protectReference
} ? *
} ? *
}
@@ -1787,7 +1793,6 @@
[ NOP ] i 2 sub logic =[]
[ NOP ] i 1 sub logic =[]
[ RAWCONSTLOOPTHISSCOPE headerBody 16 add loopBody 16 add ] i logic =[]
- /RAWCONSTLOOPTHISSCOPE dump
}
] conds
} each
@@ -1884,6 +1889,8 @@
[ NOP ] i 2 sub logic =[]
[ NOP ] i 1 sub logic =[]
[ INLINEQUESTIONSTARUNSCOPEDCONST 1 thirdLast * ::rawObject ::rawCodeAddress 1 secondLast * ::rawObject ::rawCodeAddress ] i logic =[]
+ 1 thirdLast * ::rawObject ::rawCodeAddress 16 sub ::rawObject protectReference
+ 1 secondLast * ::rawObject ::rawCodeAddress 16 sub ::rawObject protectReference
} ? *
}
] conds
@@ -2072,11 +2079,14 @@
[ s 2 add _ 8 add range peek each ] 256 math .unbase ==pushedConstant
[ PUSH pushedConstant ] emitLogic
+ pushedConstant ::rawObject protectReference
}
{ callConstantPattern match }' {
[ s 2 add _ 8 add range peek each ] 256 math .unbase ==calledAddress
calledAddress ==j
+ calledAddress 16 sub ::rawObject protectReference
+
{ { j }' { =j }' peek generalMatch }' /callTargetMatch deffst
[
{ calledAddress 105553116266496 lt }' { # HEAPBASE # FIXME: should use global constant
@@ -2088,6 +2098,7 @@
[ PUSH calledConstant ] emitLogic
[ CALL "*" | ::rawCodeAddress ] emitLogic
+ calledConstant 16 sub ::rawObject protectReference
}
{ constantNormalFunctionScopedUntypedPattern callTargetMatch }' {
@@ -2095,18 +2106,22 @@
[ calledAddress 23 add _ 8 add range peek each ] 256 math .unbase ==finalAddress
[ CALLSCOPED finalAddress functionScope ] emitLogic
+ finalAddress 16 sub ::rawObject protectReference
+ functionScope ::rawObject protectReference
}
{ constantNormalFunctionUnscopedUntypedPattern callTargetMatch }' {
[ calledAddress 2 add _ 8 add range peek each ] 256 math .unbase ==finalAddress
[ CALL finalAddress ] emitLogic
+ finalAddress 16 sub ::rawObject protectReference
}
{ constantPassivePattern callTargetMatch }' {
[ calledAddress 3 add _ 8 add range peek each ] 256 math .unbase ==pushedConstant
[ PUSH pushedConstant ] emitLogic
+ pushedConstant ::rawObject protectReference
}
{ staticLoadPattern callTargetMatch }' {
@@ -2132,6 +2147,7 @@
[ calledAddress exampleObjectOffset add _ 8 add range peek each ] 256 math .unbase ::rawObject ==exampleObject
[ STATICTYPED offsetInScope parentCount 0 exampleObject ] emitLogic
+ exampleObject protectReference
}
{ staticLoadFromExtensionPattern callTargetMatch }' {
@@ -2140,6 +2156,7 @@
[ calledAddress exampleObjectOffset add _ 8 add range peek each ] 256 math .unbase ::rawObject ==exampleObject
[ STATICTYPED offsetInScope parentCount 1 exampleObject ] emitLogic
+ exampleObject protectReference
}
{ 1 }' {
@@ -2172,12 +2189,14 @@
[ calledAddress 9 add _ 8 add range peek each ] 256 math .unbase ==pushedConstant
[ PUSH pushedConstant ] emitLogic
+ pushedConstant ::rawObject protectReference
}
{ customFunctionObjectCreationHeaderPattern callTargetMatch }' {
[ calledAddress 9 add _ 8 add range peek each ] 256 math .unbase ==functionBody # function code object address
[ FUNCTIONCREATE calledAddress functionBody ] emitLogic
+ functionBody ::rawObject protectReference
}
{ customFunctionHeaderPattern callTargetMatch }' {