constant folding 2
This commit is contained in:
parent
cf9f3af3f1
commit
121774005b
File diff suppressed because it is too large
Load Diff
@ -173,7 +173,7 @@ func (cs *CompilerState) AddUpvalue(index uint8, isLocal bool) int {
|
||||
return upvalueCount
|
||||
}
|
||||
|
||||
// Optimized constant pool management with deduplication
|
||||
// Enhanced constant pool management with better deduplication
|
||||
func (cs *CompilerState) AddConstant(value Value) int {
|
||||
// Generate unique key for deduplication
|
||||
key := cs.valueKey(value)
|
||||
@ -191,7 +191,7 @@ func (cs *CompilerState) AddConstant(value Value) int {
|
||||
return index
|
||||
}
|
||||
|
||||
// Generate unique key for value deduplication
|
||||
// Enhanced value key generation for better deduplication
|
||||
func (cs *CompilerState) valueKey(value Value) string {
|
||||
switch value.Type {
|
||||
case ValueNil:
|
||||
@ -202,15 +202,41 @@ func (cs *CompilerState) valueKey(value Value) string {
|
||||
}
|
||||
return "bool:false"
|
||||
case ValueNumber:
|
||||
return fmt.Sprintf("number:%g", value.Data.(float64))
|
||||
num := value.Data.(float64)
|
||||
// Handle special numeric values
|
||||
if num == 0 {
|
||||
return "number:0"
|
||||
} else if num == 1 {
|
||||
return "number:1"
|
||||
} else if num == -1 {
|
||||
return "number:-1"
|
||||
}
|
||||
return fmt.Sprintf("number:%g", num)
|
||||
case ValueString:
|
||||
return fmt.Sprintf("string:%s", value.Data.(string))
|
||||
str := value.Data.(string)
|
||||
if str == "" {
|
||||
return "string:empty"
|
||||
}
|
||||
// For very long strings, just use a hash to avoid memory issues
|
||||
if len(str) > 100 {
|
||||
return fmt.Sprintf("string:hash:%d", cs.simpleHash(str))
|
||||
}
|
||||
return fmt.Sprintf("string:%s", str)
|
||||
default:
|
||||
// For complex types, use memory address as fallback
|
||||
return fmt.Sprintf("%T:%p", value.Data, value.Data)
|
||||
}
|
||||
}
|
||||
|
||||
// Simple hash function for long strings
|
||||
func (cs *CompilerState) simpleHash(s string) uint32 {
|
||||
var hash uint32
|
||||
for _, c := range s {
|
||||
hash = hash*31 + uint32(c)
|
||||
}
|
||||
return hash
|
||||
}
|
||||
|
||||
// Optimized bytecode emission methods
|
||||
func (cs *CompilerState) EmitByte(byte uint8) {
|
||||
cs.Chunk.Code = append(cs.Chunk.Code, byte)
|
||||
@ -240,7 +266,7 @@ func (cs *CompilerState) PatchJump(offset int) {
|
||||
jump := len(cs.Chunk.Code) - offset - 2
|
||||
|
||||
if jump > 65535 {
|
||||
// Jump distance too large - would need to implement long jumps
|
||||
// Jump distance too large - could implement long jumps here
|
||||
return
|
||||
}
|
||||
|
||||
@ -352,7 +378,7 @@ func (cs *CompilerState) EmitStoreLocal(slot int) {
|
||||
}
|
||||
}
|
||||
|
||||
// Instruction pattern detection for optimization
|
||||
// Enhanced instruction pattern detection for optimization
|
||||
func (cs *CompilerState) GetLastInstruction() (Opcode, []uint16) {
|
||||
if len(cs.Chunk.Code) == 0 {
|
||||
return OpNoop, nil
|
||||
@ -367,8 +393,10 @@ func (cs *CompilerState) GetLastInstruction() (Opcode, []uint16) {
|
||||
// This is a complete instruction
|
||||
operands := make([]uint16, operandCount)
|
||||
for j := 0; j < operandCount; j++ {
|
||||
operands[j] = uint16(cs.Chunk.Code[i+1+j*2]) |
|
||||
(uint16(cs.Chunk.Code[i+2+j*2]) << 8)
|
||||
if i+1+j*2 < len(cs.Chunk.Code) && i+2+j*2 < len(cs.Chunk.Code) {
|
||||
operands[j] = uint16(cs.Chunk.Code[i+1+j*2]) |
|
||||
(uint16(cs.Chunk.Code[i+2+j*2]) << 8)
|
||||
}
|
||||
}
|
||||
return op, operands
|
||||
}
|
||||
@ -402,50 +430,6 @@ func (cs *CompilerState) ReplaceLastInstruction(op Opcode, operands ...uint16) b
|
||||
return true
|
||||
}
|
||||
|
||||
// Constant folding support
|
||||
func (cs *CompilerState) TryConstantFolding(op Opcode, operands ...Value) *Value {
|
||||
if len(operands) < 2 {
|
||||
return nil
|
||||
}
|
||||
|
||||
left, right := operands[0], operands[1]
|
||||
|
||||
// Only fold numeric operations for now
|
||||
if left.Type != ValueNumber || right.Type != ValueNumber {
|
||||
return nil
|
||||
}
|
||||
|
||||
l := left.Data.(float64)
|
||||
r := right.Data.(float64)
|
||||
|
||||
switch op {
|
||||
case OpAdd:
|
||||
return &Value{Type: ValueNumber, Data: l + r}
|
||||
case OpSub:
|
||||
return &Value{Type: ValueNumber, Data: l - r}
|
||||
case OpMul:
|
||||
return &Value{Type: ValueNumber, Data: l * r}
|
||||
case OpDiv:
|
||||
if r != 0 {
|
||||
return &Value{Type: ValueNumber, Data: l / r}
|
||||
}
|
||||
case OpEq:
|
||||
return &Value{Type: ValueBool, Data: l == r}
|
||||
case OpNeq:
|
||||
return &Value{Type: ValueBool, Data: l != r}
|
||||
case OpLt:
|
||||
return &Value{Type: ValueBool, Data: l < r}
|
||||
case OpLte:
|
||||
return &Value{Type: ValueBool, Data: l <= r}
|
||||
case OpGt:
|
||||
return &Value{Type: ValueBool, Data: l > r}
|
||||
case OpGte:
|
||||
return &Value{Type: ValueBool, Data: l >= r}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Dead code elimination support
|
||||
func (cs *CompilerState) MarkUnreachable(start, end int) {
|
||||
if start >= 0 && end <= len(cs.Chunk.Code) {
|
||||
@ -461,12 +445,14 @@ type OptimizationStats struct {
|
||||
InstructionsOpt int
|
||||
DeadCodeEliminated int
|
||||
JumpsOptimized int
|
||||
ConstantsDeduped int
|
||||
}
|
||||
|
||||
func (cs *CompilerState) GetOptimizationStats() OptimizationStats {
|
||||
// Count specialized instructions used
|
||||
specialized := 0
|
||||
noops := 0
|
||||
constantsDeduped := len(cs.Constants) - len(cs.Chunk.Constants)
|
||||
|
||||
for i := 0; i < len(cs.Chunk.Code); {
|
||||
op, _, next := DecodeInstruction(cs.Chunk.Code, i)
|
||||
@ -482,6 +468,7 @@ func (cs *CompilerState) GetOptimizationStats() OptimizationStats {
|
||||
return OptimizationStats{
|
||||
InstructionsOpt: specialized,
|
||||
DeadCodeEliminated: noops,
|
||||
ConstantsDeduped: constantsDeduped,
|
||||
}
|
||||
}
|
||||
|
||||
@ -489,13 +476,31 @@ func (cs *CompilerState) SetLine(line int) {
|
||||
cs.CurrentLine = line
|
||||
}
|
||||
|
||||
// Debugging support
|
||||
// Enhanced debugging support
|
||||
func (cs *CompilerState) PrintChunk(name string) {
|
||||
fmt.Printf("== %s ==\n", name)
|
||||
fmt.Printf("Constants: %d\n", len(cs.Chunk.Constants))
|
||||
fmt.Printf("Functions: %d\n", len(cs.Chunk.Functions))
|
||||
fmt.Printf("Structs: %d\n", len(cs.Chunk.Structs))
|
||||
fmt.Printf("Code size: %d bytes\n", len(cs.Chunk.Code))
|
||||
|
||||
stats := cs.GetOptimizationStats()
|
||||
fmt.Printf("Optimizations: %d specialized, %d dead eliminated, %d constants deduped\n",
|
||||
stats.InstructionsOpt, stats.DeadCodeEliminated, stats.ConstantsDeduped)
|
||||
fmt.Println()
|
||||
|
||||
for offset := 0; offset < len(cs.Chunk.Code); {
|
||||
offset = cs.disassembleInstruction(offset)
|
||||
}
|
||||
|
||||
if len(cs.Chunk.Constants) > 0 {
|
||||
fmt.Println("\nConstants:")
|
||||
for i, constant := range cs.Chunk.Constants {
|
||||
fmt.Printf("%4d: ", i)
|
||||
cs.printValue(constant)
|
||||
fmt.Println()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (cs *CompilerState) disassembleInstruction(offset int) int {
|
||||
@ -528,12 +533,14 @@ func (cs *CompilerState) disassembleInstruction(offset int) int {
|
||||
switch op {
|
||||
case OpLoadConst:
|
||||
return cs.constantInstruction(offset)
|
||||
case OpLoadLocal, OpStoreLocal:
|
||||
case OpLoadLocal, OpStoreLocal, OpAddConst, OpSubConst, OpInc, OpDec:
|
||||
return cs.byteInstruction(offset)
|
||||
case OpJump, OpJumpIfTrue, OpJumpIfFalse:
|
||||
return cs.jumpInstruction(offset, 1)
|
||||
case OpLoopBack:
|
||||
return cs.jumpInstruction(offset, -1)
|
||||
case OpGetLocalField, OpSetLocalField, OpTestAndJump:
|
||||
return cs.doubleByteInstruction(offset)
|
||||
default:
|
||||
fmt.Println()
|
||||
return offset + 1
|
||||
@ -570,6 +577,18 @@ func (cs *CompilerState) byteInstruction(offset int) int {
|
||||
return offset + 3
|
||||
}
|
||||
|
||||
func (cs *CompilerState) doubleByteInstruction(offset int) int {
|
||||
if offset+4 >= len(cs.Chunk.Code) {
|
||||
fmt.Println(" [incomplete]")
|
||||
return offset + 1
|
||||
}
|
||||
|
||||
arg1 := uint16(cs.Chunk.Code[offset+1]) | (uint16(cs.Chunk.Code[offset+2]) << 8)
|
||||
arg2 := uint16(cs.Chunk.Code[offset+3]) | (uint16(cs.Chunk.Code[offset+4]) << 8)
|
||||
fmt.Printf(" %4d %4d\n", arg1, arg2)
|
||||
return offset + 5
|
||||
}
|
||||
|
||||
func (cs *CompilerState) jumpInstruction(offset int, sign int) int {
|
||||
if offset+2 >= len(cs.Chunk.Code) {
|
||||
fmt.Println(" [incomplete]")
|
||||
@ -593,9 +612,14 @@ func (cs *CompilerState) printValue(value Value) {
|
||||
fmt.Print("false")
|
||||
}
|
||||
case ValueNumber:
|
||||
fmt.Printf("%.2g", value.Data.(float64))
|
||||
fmt.Printf("%.6g", value.Data.(float64))
|
||||
case ValueString:
|
||||
fmt.Printf("\"%s\"", value.Data.(string))
|
||||
str := value.Data.(string)
|
||||
if len(str) > 50 {
|
||||
fmt.Printf("\"%s...\"", str[:47])
|
||||
} else {
|
||||
fmt.Printf("\"%s\"", str)
|
||||
}
|
||||
default:
|
||||
fmt.Printf("<%s>", cs.valueTypeString(value.Type))
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user