aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDrahflow <drahflow@gmx.de>2013-09-24 10:40:37 +0200
committerDrahflow <drahflow@gmx.de>2013-09-24 10:40:37 +0200
commitc2182784d2237b15dddebec66473a5726faa07a4 (patch)
tree02943cc1fb8d8886d2a0abb00e1d3769e92beb25
parentbd4fe14e2a77ceac5c8c234de05c514fdd6d7bf4 (diff)
Saner patching of static loads
-rw-r--r--compiler/elymasAsm.ey20
-rw-r--r--compiler/elymasGlobal.ey142
-rw-r--r--compiler/standardClient.ey14
-rw-r--r--elymas/lib/sys/opt.ey133
4 files changed, 165 insertions, 144 deletions
diff --git a/compiler/elymasAsm.ey b/compiler/elymasAsm.ey
index fcb584a..15ed57b 100644
--- a/compiler/elymasAsm.ey
+++ b/compiler/elymasAsm.ey
@@ -12,16 +12,16 @@
} "%" defq
# registers
- < [ /rax /rcx /rdx /rbx /rsp /rbp /rsi /rdi /r8 /r9 /r10 /r11 /r12 /r13 /r14 /r15 ] { 1 -01 defv }' each > ==bit64table
+ < [ /rax /rcx /rdx /rbx /rsp /rbp /rsi /rdi /r8 /r9 /r10 /r11 /r12 /r13 /r14 /r15 ] { 1 -01 defv }' each > ==:bit64table
{ bit64table -01 . -- } /bit64assert deff
- < [ /eax /ecx /edx /ebx /esp /ebp /esi /edi /r8d /r9d /r10d /r11d /r12d /r13d /r14d /r15d ] { 1 -01 defv }' each > ==bit32table
+ < [ /eax /ecx /edx /ebx /esp /ebp /esi /edi /r8d /r9d /r10d /r11d /r12d /r13d /r14d /r15d ] { 1 -01 defv }' each > ==:bit32table
{ bit32table -01 . -- } /bit32assert deff
- < [ /ax /cx /dx /bx /sp /bp /si /di /r8w /r9w /r10w /r11w /r12w /r13w /r14w /r15w ] { 1 -01 defv }' each > ==bit16table
+ < [ /ax /cx /dx /bx /sp /bp /si /di /r8w /r9w /r10w /r11w /r12w /r13w /r14w /r15w ] { 1 -01 defv }' each > ==:bit16table
{ bit16table -01 . -- } /bit16assert deff
- < [ /al /cl /dl /bl /spl /ah /bpl /ch /sil /dh /dil /bh /r8b /r9b /r10b /r11b /r12b /r13b /r14b /r15b ] { 1 -01 defv }' each > ==bit8table
+ < [ /al /cl /dl /bl /spl /ah /bpl /ch /sil /dh /dil /bh /r8b /r9b /r10b /r11b /r12b /r13b /r14b /r15b ] { 1 -01 defv }' each > ==:bit8table
{ bit8table -01 . -- } /bit8assert deff
<
@@ -41,7 +41,7 @@
[ /r13b /r13w /r13d /r13 ] { 13 -01 defv }' each
[ /r14b /r14w /r14d /r14 ] { 14 -01 defv }' each
[ /r15b /r15w /r15d /r15 ] { 15 -01 defv }' each
- > ==regnoTable
+ > ==:regnoTable
{ regnoTable -01 . } /regno deff
@@ -49,7 +49,7 @@
[ /al /cl /dl /bl ] { 0 -01 defv }' each
[ /spl /bpl /sil /dil ] { 1 -01 defv }' each
[ /r8b /r9b /r10b /r11b /r12b /r13b /r14b /r15b ] { 1 -01 defv }' each
- > ==rexreqbyteTable
+ > ==:rexreqbyteTable
{ rexreqbyteTable -01 . } /rexreqbyte deff
@@ -228,13 +228,13 @@
} /encode deff >
} ==Mem
# base register plus 8 bit displacement
- { < _ bit64assert ==base _ 128 lt assert ==disp /none ==idx { ==r
+ { < _ bit64assert ==base /none ==idx _ 128 lt assert ==disp { ==r
r base modrm01
disp imm8
} /encode deff >
} ==MemDisp8
# base register plus 32 bit displacement
- { < _ bit64assert ==base ==disp /none ==idx { ==r
+ { < _ bit64assert ==base /none ==idx ==disp { ==r
r base modrm10
disp imm32
} /encode deff >
@@ -1196,10 +1196,10 @@
}' each
STACKSIZE sys .asm .alloc _ globalAllocations .register
- .base ==quoteEncodingBufferCode
+ .base ==:quoteEncodingBufferCode
STACKSIZE sys .asm .alloc _ globalAllocations .register
- .base ==quoteEncodingBufferObjects
+ .base ==:quoteEncodingBufferObjects
{ ==opcodes
opcodes len 1 sub PAGESIZE div 1 add PAGESIZE mul sys .asm .alloc /codearea defv
diff --git a/compiler/elymasGlobal.ey b/compiler/elymasGlobal.ey
index 1820725..1b36b1b 100644
--- a/compiler/elymasGlobal.ey
+++ b/compiler/elymasGlobal.ey
@@ -1079,7 +1079,7 @@
%40 /dl :testbImmReg
/patchConstant :jnzLbl8
- %10 /dl :testbImmReg
+ %30 /dl :testbImmReg # TODO separate cases for static and typed
/patchStatic :jnzLbl32
/rdx /rcx :movqRegReg
@@ -1102,11 +1102,11 @@
/rax :callqReg
:ud2
- @active
+ @active # TODO patch late resolve call away
|ey* /rax :movqImmReg
/rax :callqReg
- @inactive
+ @inactive # TODO patch late resolve call away
@done
16 /r15 :addqImm8Reg
@@ -1301,18 +1301,38 @@
:ud2
@patchStaticPassive
+ 0 /rax :movqImmReg
+ /rax :pushqReg
+ /patchStaticImplementation :jmpLbl8
+
+ @patchStaticActive
+ 1 /rax :movqImmReg
+ /rax :pushqReg
+
+ @patchStaticImplementation
+
/rdi /rcx :movqRegReg # save parent pointer count
# FIXME: keep enough place for repeated parent dereference when creating the to-be-patched-code
15 /rcx :cmpqImm8Reg
- /patchStaticPassiveParentCountWithinLimits :jbeLbl8
+ /patchStaticParentCountWithinLimits :jbeLbl8
"parent count out of save limits in internalExecuteIdentifierUnquotedAndPatchLateResolve" ::outputError
:ud2
- @patchStaticPassiveParentCountWithinLimits
+ @patchStaticParentCountWithinLimits
8 /r15 /rdi :movqMemDisp8Reg
- # TODO: could reset string reference here
+ # replace string reference with example object (for later optimizer inspection)
+ 8 /rdi /rdx :movqMemDisp8Reg
+ 16 1 /rdx /rdi /rdx :leaqMemIndexScaleDisp8Reg
+ /rdi /eax :movlMemReg
+ /rdi /rax :addqRegReg
+ /rdx /rax :cmpqRegReg
+ /patchStaticParentCountWithinLimitsSpaceExists :jaLbl8
+ "no space available for example object" ::outputError
+ :ud2
+ @patchStaticParentCountWithinLimitsSpaceExists
+ 0 /rdx :andqImm8Mem # reset example object pointer
16 /rdi :addqImm8Reg
[
@@ -1321,125 +1341,67 @@
] ::loadToRdi
/rcx /rcx :testqRegReg
- /patchStaticPassiveNoFollowParents :jzLbl8
- @patchStaticPassiveFollowParents
+ /patchStaticNoFollowParents :jzLbl8
+ @patchStaticFollowParents
[
16 /rax /rax :movqMemDisp8Reg
] ::loadToRdi
- /patchStaticPassiveFollowParents :loopLbl8
- @patchStaticPassiveNoFollowParents
+ /patchStaticFollowParents :loopLbl8
+ @patchStaticNoFollowParents
%01 /bpl :testbImmReg
- /patchStaticPassiveLoadFromExtensionArea :jnzLbl8
+ /patchStaticLoadFromExtensionArea :jnzLbl8
- # @patchStaticPassiveLoadFromScope
+ # @patchStaticLoadFromScope
32 /rsi :addqImm8Reg # now: rsi == offset of entry in scope
[
/rbx :popqReg
- %EE /rax :pushqMemDisp32
- /rbx :jmpqReg
+ %EE /rax /rax :movqMemDisp32Reg
] ::loadToRdi
- 6 /rdi :subqImm8Reg
- /esi /rdi :movlRegMem # patch offset
-
- 8 /r15 /rdi :movqMemDisp8Reg
- 16 /rdi :addqImm8Reg
-
- 16 /r15 :addqImm8Reg
- /r15 :pushqMem
- 8 /r15 :addqImm8Reg
- /rdi :jmpqReg # continue with freshly patched code
+ /esi 4 neg /rdi :movlRegMemDisp8 # patch offset
+ /patchStaticLoadTail :jmpLbl8
- @patchStaticPassiveLoadFromExtensionArea
+ @patchStaticLoadFromExtensionArea
40 /rsi :addqImm8Reg # now: rsi == offset of entry in extension area + scope length
-
[
24 /rax /rcx :movqMemDisp8Reg # load extension area pointer
/rax /edx :movlMemReg # load scope length
/rdx :negqReg # prepare for substraction
/rbx :popqReg
- %EE 1 /rdx /rcx :pushqMemIndexScaleDisp32 # push loaded entry to stack
- /rbx :jmpqReg
+ %EE 1 /rdx /rcx /rax :movqMemIndexScaleDisp32Reg # load entry
] ::loadToRdi
- 6 /rdi :subqImm8Reg
- /esi /rdi :movlRegMem # patch offset
-
- 8 /r15 /rdi :movqMemDisp8Reg
- 16 /rdi :addqImm8Reg
-
- 16 /r15 :addqImm8Reg
- /r15 :pushqMem
- 8 /r15 :addqImm8Reg
- /rdi :jmpqReg # continue with freshly patched code
-
- @patchStaticActive
- /rdi /rcx :movqRegReg # save parent pointer count
- # FIXME: keep enough place for repeated parent dereference when creating the to-be-patched-code
-
- 15 /rcx :cmpqImm8Reg
- /patchStaticActiveParentCountWithinLimits :jbeLbl8
-
- "parent count out of save limits in internalExecuteIdentifierUnquotedAndPatchLateResolve" ::outputError
- :ud2
-
- @patchStaticActiveParentCountWithinLimits
- 8 /r15 /rdi :movqMemDisp8Reg
- # TODO: could reset string reference here
- 16 /rdi :addqImm8Reg
+ /esi 4 neg /rdi :movlRegMemDisp8 # patch offset
+ @patchStaticLoadTail
[
- ::currentScope /rax :movqImmReg
- /rax /rax :movqMemReg
+ /rax :pushqReg
+ /rcx :movqImmOOBReg
] ::loadToRdi
-
- /rcx /rcx :testqRegReg
- /patchStaticActiveNoFollowParents :jzLbl8
- @patchStaticActiveFollowParents
+ /rdx /rdi :movqRegMem
+ 8 /rdi :addqImm8Reg
[
- 16 /rax /rax :movqMemDisp8Reg
+ /rax /rcx :movqRegMem
] ::loadToRdi
- /patchStaticActiveFollowParents :loopLbl8
- @patchStaticActiveNoFollowParents
- %01 /bpl :testbImmReg
- /patchStaticActiveLoadFromExtensionArea :jnzLbl8
+ /rax :popqReg
+ /rax /rax :testqRegReg
+ /patchStaticLoadActive :jnzLbl8
- # @patchStaticActiveLoadFromScope
- 32 /rsi :addqImm8Reg # now: rsi == offset of entry in scope
+ # @patchStaticLoadPassive
[
- /rbx :popqReg
- %EE /rax :pushqMemDisp32
- /rbx :pushqReg
- |ey* /rax :movqImmReg
- /rax :jmpqReg
+ /rbx :jmpqReg
] ::loadToRdi
- 17 /rdi :subqImm8Reg
- /esi /rdi :movlRegMem # patch offset
-
- 8 /r15 /rdi :movqMemDisp8Reg
- 16 /rdi :addqImm8Reg
-
- 16 /r15 :addqImm8Reg
- /r15 :pushqMem
- 8 /r15 :addqImm8Reg
- /rdi :jmpqReg # continue with freshly patched code
- @patchStaticActiveLoadFromExtensionArea
- 40 /rsi :addqImm8Reg # now: rsi == offset of entry in extension area + scope length
+ /patchStaticLoadTail2 :jmpLbl8
+ @patchStaticLoadActive
[
- 24 /rax /rcx :movqMemDisp8Reg # load extension area pointer
- /rax /edx :movlMemReg # load scope length
- /rdx :negqReg # prepare for substraction
- /rbx :popqReg
- %EE 1 /rdx /rcx :pushqMemIndexScaleDisp32 # push loaded entry to stack
/rbx :pushqReg
|ey* /rax :movqImmReg
/rax :jmpqReg
] ::loadToRdi
- 17 /rdi :subqImm8Reg
- /esi /rdi :movlRegMem # patch offset
+ @patchStaticLoadTail2
8 /r15 /rdi :movqMemDisp8Reg
16 /rdi :addqImm8Reg
diff --git a/compiler/standardClient.ey b/compiler/standardClient.ey
index 643a805..e00279f 100644
--- a/compiler/standardClient.ey
+++ b/compiler/standardClient.ey
@@ -220,17 +220,20 @@
}" /cloneThread deffd
{ #==thread ==newpc
+ 0 -1201 =[]
+ }" /updateThread deffd
+
+ { #==thread ==newpc
[ -0201 threadGetCaptures _ len dearray ] ]
}" /fullCloneThread deffd
|add /origadd deffd
+ str .|bitTest /bitTest deffd
+ str .|bitSet /bitSet deffd
+ str .|zero /zero deffd
# TODO think about implementation efficiency
{ ==maxSize
- str .|bitTest /bitTest deffd
- str .|bitSet /bitSet deffd
- str .|zero /zero deffd
-
<
0 ==size
[ maxSize { 0 }" rep ] =*get
@@ -281,7 +284,7 @@
clist .clear
}" { # TERM
position maxPosition lt {
- position string * 1 code * { pc 1 add thread cloneThread nlist .add }" rep
+ position string * 1 code * { pc 1 add thread updateThread nlist .add }" rep
}" rep
}" { # JUMP
pc 1 code add thread cloneThread iPush
@@ -302,6 +305,7 @@
0 ==i
{ position maxPosition le }" {
0 =i
+
{ i clist .size lt }" {
i clist .get _ =thread
threadGetPC _ =pc
diff --git a/elymas/lib/sys/opt.ey b/elymas/lib/sys/opt.ey
index bd7600f..b281171 100644
--- a/elymas/lib/sys/opt.ey
+++ b/elymas/lib/sys/opt.ey
@@ -85,37 +85,32 @@
[
/rbx :popqReg
- 0 /rax :pushqMemDisp32
- /rbx :jmpqReg
- ] ==:staticLoadPassiveFromScopePattern
+ 0 /rax /rax :movqMemDisp32Reg
+ ] ==:staticLoadFromScopePattern
[
24 /rax /rcx :movqMemDisp8Reg # load extension area pointer
/rax /edx :movlMemReg # load scope length
/rdx :negqReg # prepare for substraction
/rbx :popqReg
- 0 1 /rdx /rcx :pushqMemIndexScaleDisp32 # push loaded entry to stack
- /rbx :jmpqReg
- ] ==:staticLoadPassiveFromExtensionPattern
+ 0 1 /rdx /rcx /rax :movqMemIndexScaleDisp32Reg # load entry
+ ] ==:staticLoadFromExtensionPattern
[
- /rbx :popqReg
- 0 /rax :pushqMemDisp32
- /rbx :pushqReg
- 0 /rax :movqImmReg
- /rax :jmpqReg
- ] ==:staticLoadActiveFromScopePattern
+ /rax :pushqReg
+ 0 /rcx :movqImmReg
+ /rax /rcx :movqRegMem
+ /rbx :jmpqReg
+ ] ==:staticLoadPassivePattern
[
- 24 /rax /rcx :movqMemDisp8Reg # load extension area pointer
- /rax /edx :movlMemReg # load scope length
- /rdx :negqReg # prepare for substraction
- /rbx :popqReg
- 0 1 /rdx /rcx :pushqMemIndexScaleDisp32 # push loaded entry to stack
+ /rax :pushqReg
+ 0 /rcx :movqImmReg
+ /rax /rcx :movqRegMem
/rbx :pushqReg
0 /rax :movqImmReg
/rax :jmpqReg
- ] ==:staticLoadActiveFromExtensionPattern
+ ] ==:staticLoadActivePattern
[
8 /r15 :subqImm8Reg
@@ -127,7 +122,9 @@
/CALL ==:CALL
/CALLSCOPED ==:CALLSCOPED
/STATIC ==:STATIC
+ /STATICTYPED ==:STATICTYPED
/STATICWRITE ==:STATICWRITE
+ /STATICDOT ==:STATICDOT
/NATIVE ==:NATIVE
{ =*f ==t
@@ -152,7 +149,7 @@
} /testScopeModifications deffst
{ ==logic
- [ /NOP ] ==last
+ [ NOP ] ==last
[ logic { ==entry 0 entry * ==action
[
{ action CALL streq { 1 entry * "|" | +rawCodeAddress eq }' andif { 0 last * PUSH streq }' andif }' {
@@ -164,7 +161,7 @@
mode 16 div 1 band {
[ STATIC offsetInScope parentCount inExtensionArea ] =last
- [ /NOP ] =entry
+ [ NOP ] =entry
} { } ? *
} {
executingScope dump
@@ -181,7 +178,7 @@
} /rewriteConstantPipe deffst
{ ==logic
- [ /NOP ] ==last
+ [ NOP ] ==last
[ logic { ==entry 0 entry * ==action
[
{ action CALL streq { 1 entry * "=" | +rawCodeAddress eq }' andif { 0 last * PUSH streq }' andif }' {
@@ -193,7 +190,7 @@
mode 16 div 1 band {
[ STATICWRITE offsetInScope parentCount inExtensionArea ] =last
- [ /NOP ] =entry
+ [ NOP ] =entry
} { } ? *
} {
executingScope dump
@@ -209,8 +206,42 @@
} each last ]
} /rewriteConstantEquals deffst
+ { _ ==logic
+ 2 logic len range { ==i i logic * ==entry 0 entry * ==action i 1 sub logic * ==last i 2 sub logic * ==secondLast
+ [
+ { action CALL streq
+ { 1 entry * "." | +rawCodeAddress eq }' andif
+ { 0 last * PUSH streq }' andif
+ { 0 secondLast * STATICTYPED streq }' andif
+ }' {
+ 1 last * +rawObject ==constant
+ 4 secondLast * +rawObject ==relevantScope
+
+ constant relevantScope sys .resolveInfo {
+ ==mode -- ==parentCount 32 add ==offsetInScope ==inExtensionArea
+ inExtensionArea { offsetInScope 8 add =offsetInScope } rep
+
+ mode 16 div 1 band {
+ [ STATICDOT offsetInScope parentCount inExtensionArea ] i 1 sub logic =[]
+ mode 1 band { # TODO bail out for activation mode of 2
+ [ CALL "*" | +rawCodeAddress ] i logic =[]
+ } {
+ [ NOP ] i logic =[]
+ } ? *
+ } { } ? *
+ } {
+ relevantScope dump
+ relevantScope keys dump
+ constant dump
+ "resolution failed" die
+ } ? *
+ }
+ ] conds
+ } each
+ } /rewriteConstantDot deffst
+
{ ==logic
- [ /NOP ] ==last
+ [ NOP ] ==last
[ logic { ==entry 0 entry * ==action
[
{ action CALL streq { 1 entry * "_" | +rawCodeAddress eq }' andif }' {
@@ -306,30 +337,37 @@
j ==loadStart
[
- { staticLoadPassiveFromScopePattern callTargetMatch }' {
- [ loadStart 3 add _ 4 add range peek each ] 256 math .unbase ==offsetInScope
+ { staticLoadFromScopePattern callTargetMatch }' {
+ [ loadStart 4 add _ 4 add range peek each ] 256 math .unbase ==offsetInScope
+ [ calledAddress 8 sub _ 8 add range peek each ] 256 math .unbase ==exampleObjectOffset
+ [ calledAddress exampleObjectOffset add _ 8 add range peek each ] 256 math .unbase ==exampleObject
- [ STATIC offsetInScope parentCount 0 ] emitLogic
+ [ STATICTYPED offsetInScope parentCount 0 exampleObject ] emitLogic
}
- { staticLoadPassiveFromExtensionPattern callTargetMatch }' {
- [ loadStart 13 add _ 4 add range peek each ] 256 math .unbase ==offsetInScope
+ { staticLoadFromExtensionPattern callTargetMatch }' {
+ [ loadStart 14 add _ 4 add range peek each ] 256 math .unbase ==offsetInScope
+ [ calledAddress 8 sub _ 8 add range peek each ] 256 math .unbase ==exampleObjectOffset
+ [ calledAddress exampleObjectOffset add _ 8 add range peek each ] 256 math .unbase ==exampleObject
- [ STATIC offsetInScope parentCount 1 ] emitLogic
+ [ STATICTYPED offsetInScope parentCount 1 exampleObject ] emitLogic
}
- { staticLoadActiveFromScopePattern callTargetMatch }' {
- [ loadStart 3 add _ 4 add range peek each ] 256 math .unbase ==offsetInScope
+ { 1 }' {
+ [ j j 16 add range peek each ] dump
+ o dump
+ j dump
+ "unparsed static load opcodes in sys .opt .hook (optimizing version)" die
+ }
+ ] conds
- [ STATIC offsetInScope parentCount 0 ] emitLogic
+ [
+ { staticLoadActivePattern callTargetMatch }' {
[ CALL "*" | +rawCodeAddress ] emitLogic
}
- { staticLoadActiveFromExtensionPattern callTargetMatch }' {
- [ loadStart 13 add _ 4 add range peek each ] 256 math .unbase ==offsetInScope
-
- [ STATIC offsetInScope parentCount 1 ] emitLogic
- [ CALL "*" | +rawCodeAddress ] emitLogic
+ { staticLoadPassivePattern callTargetMatch }' {
+ # nothing to emit
}
{ 1 }' {
@@ -396,6 +434,7 @@
testScopeModifications
containsScopeModifications not |rewriteConstantPipe rep
containsScopeModifications not |rewriteConstantEquals rep
+ containsScopeModifications not |rewriteConstantDot rep
rewriteStackOps
{ =*entry 0 entry ==action
[
@@ -439,7 +478,7 @@
2 entry emitReference
}
- { action STATIC streq }' {
+ { action [ STATIC STATICTYPED ] streq any }' {
[
::currentScope /rax :movqImmReg
/rax /rax :movqMemReg
@@ -448,7 +487,7 @@
3 entry {
24 /rax /rcx :movqMemDisp8Reg # load extension area pointer
/rax /edx :movlMemReg # load scope length
- /rdx :negqReg # prepare for substraction
+ /rdx :negqReg # prepare for substraction # TODO the length calculation could be done beforehand
1 entry 1 /rdx /rcx :pushqMemIndexScaleDisp32 # push loaded entry to stack
} {
1 entry /rax :pushqMemDisp32
@@ -473,6 +512,22 @@
] emitOpcodes
}
+ { action STATICDOT streq }' {
+ [
+ /rax :popqReg
+ 2 entry { 16 /rax /rax :movqMemDisp8Reg } rep
+
+ 3 entry {
+ 24 /rax /rcx :movqMemDisp8Reg # load extension area pointer
+ /rax /edx :movlMemReg # load scope length
+ /rdx :negqReg # prepare for substraction
+ 1 entry 1 /rdx /rcx :pushqMemIndexScaleDisp32 # push loaded entry to stack
+ } {
+ 1 entry /rax :pushqMemDisp32
+ } ? *
+ ] emitOpcodes
+ }
+
{ action NATIVE streq }' {
1 entry emitOpcodes
}