Skip to content

Commit 59f6bd2

Browse files
mi-acV8-internal LUCI CQ
authored andcommitted
Improve class-definition generation
Previously there were two code generators for classes, the ClassDefinitionGenerator and the WeirdClassGenerator. The former was still an old-style generator, so it could not be scheduled for any of the ~20 generators that require the classDefinition context. So all such generators scheduled the WeirdClassGenerator, which forced a simple method as superclass, which in return doesn't contain any interesting code as in e.g. the ObjectConstructorGenerator. This change unifies the two class generators as one new-style generator. The generator provides the classDefinition context, so it can be scheduled for parts of classes. It also produces a constructor() (unlike the WeirdClassGenerator), so it can be scheduled for generators that require constructor()-type input. Bug: 446632644 Change-Id: I7313dae3998cdd0ff488779debeca7c6ab333fc9 Reviewed-on: https://chrome-internal-review.googlesource.com/c/v8/fuzzilli/+/8705459 Commit-Queue: Michael Achenbach <machenbach@google.com> Reviewed-by: Matthias Liedtke <mliedtke@google.com>
1 parent dcbbafd commit 59f6bd2

3 files changed

Lines changed: 44 additions & 59 deletions

File tree

Sources/Fuzzilli/CodeGen/CodeGeneratorWeights.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,6 @@ public let codeGeneratorWeights = [
192192
"PrototypeOverwriteGenerator": 10,
193193
"CallbackPropertyGenerator": 10,
194194
"MethodCallWithDifferentThisGenerator": 5,
195-
"WeirdClassGenerator": 10,
196195
"ProxyGenerator": 10,
197196
"LengthChangeGenerator": 5,
198197
"ElementKindChangeGenerator": 5,

Sources/Fuzzilli/CodeGen/CodeGenerators.swift

Lines changed: 39 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -367,39 +367,46 @@ public let CodeGenerators: [CodeGenerator] = [
367367
}
368368
},
369369

370-
CodeGenerator("ClassDefinitionGenerator", produces: [.constructor()]) { b in
371-
// Possibly pick a superclass. The superclass must be a constructor (or null), otherwise a type error will be raised at runtime.
372-
var superclass: Variable? = nil
373-
if probability(0.5) && b.hasVisibleVariables {
374-
superclass = b.randomVariable(ofType: .constructor())
375-
}
376-
377-
// If there are no visible variables, create some random number- or string values first, so they can be used for example as property values.
378-
if !b.hasVisibleVariables {
379-
for _ in 0..<3 {
380-
withEqualProbability(
381-
{
382-
b.loadInt(b.randomInt())
383-
},
384-
{
385-
b.loadFloat(b.randomFloat())
386-
},
387-
{
388-
b.loadString(b.randomString())
389-
})
390-
}
391-
}
392-
393-
// Create the class.
394-
let c = b.buildClassDefinition(withSuperclass: superclass, isExpression: probability(0.3)) { cls in
395-
b.buildRecursive(n: defaultCodeGenerationAmount)
396-
}
370+
CodeGenerator(
371+
"ClassDefinitionGenerator",
372+
[
373+
GeneratorStub(
374+
"ClassDefinitionBeginGenerator",
375+
produces: [.constructor()],
376+
provides: [.classDefinition]
377+
) { b in
378+
// Possibly pick a superclass.
379+
// The superclass must be a constructor (or null).
380+
var superclass: Variable? = nil
381+
if probability(0.4) && b.hasVisibleVariables {
382+
superclass = b.randomVariable(ofType: .constructor())
383+
} else if probability(0.2) {
384+
superclass = b.buildPlainFunction(with: .parameters(n: 1)) {
385+
args in
386+
b.doReturn(b.randomJsVariable())
387+
}
388+
}
389+
let inputs = superclass != nil ? [superclass!] : []
390+
let cls = b.emit(BeginClassDefinition(
391+
hasSuperclass: superclass != nil,
392+
isExpression: probability(0.3)),
393+
withInputs: inputs).output
394+
b.runtimeData.push("class", cls)
395+
},
396+
GeneratorStub(
397+
"ClassDefinitionEndGenerator",
398+
inContext: .single(.classDefinition)
399+
) { b in
400+
b.emit(EndClassDefinition())
397401

398-
// And construct a few instances of it.
399-
for _ in 0..<Int.random(in: 1...4) {
400-
b.construct(c, withArgs: b.randomArguments(forCalling: c))
401-
}
402-
},
402+
// Construct a few instances of the class.
403+
let cls = b.runtimeData.pop("class")
404+
for _ in 0..<Int.random(in: 0...4) {
405+
b.construct(cls, withArgs: b.randomArguments(forCalling: cls))
406+
}
407+
},
408+
]
409+
),
403410

404411
CodeGenerator("TrivialFunctionGenerator", produces: [.function()]) { b in
405412
// Generating more than one function has a fairly high probability of generating
@@ -2485,31 +2492,6 @@ public let CodeGenerators: [CodeGenerator] = [
24852492
b.callMethod("construct", on: reflect, withArgs: arguments)
24862493
},
24872494

2488-
CodeGenerator(
2489-
"WeirdClassGenerator",
2490-
[
2491-
GeneratorStub(
2492-
"WeirdClassBeginGenerator",
2493-
provides: [.classDefinition]
2494-
) { b in
2495-
// See basically https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/Private_class_fields#examples
2496-
let base = b.buildPlainFunction(with: .parameters(n: 1)) {
2497-
args in
2498-
b.doReturn(b.randomJsVariable())
2499-
}
2500-
b.emit(
2501-
BeginClassDefinition(hasSuperclass: true, isExpression: probability(0.3)),
2502-
withInputs: [base])
2503-
},
2504-
GeneratorStub(
2505-
"WeirdClassGenerator",
2506-
inContext: .single(.classDefinition)
2507-
) { b in
2508-
b.emit(EndClassDefinition())
2509-
},
2510-
]
2511-
),
2512-
25132495
CodeGenerator("ProxyGenerator", inputs: .preferred(.object())) {
25142496
b, target in
25152497
var candidates = Set([

Sources/Fuzzilli/FuzzIL/JSTyper.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1118,7 +1118,11 @@ public struct JSTyper: Analyzer {
11181118

11191119
dynamicObjectGroupManager.createNewClass(withSuperType: superType, propertyMap: propertySuperTypeMap, methodMap: methodSuperTypeMap, superConstructorType: superConstructorType, forOutput: instr.output)
11201120

1121-
set(instr.output, .jsAnything) // Treat the class variable as unknown until we have fully analyzed the class definition
1121+
// We only know here that this is going to be a constructor() type.
1122+
// On endClassDefinition below, the exact type is refined. But we
1123+
// need to already set this broader type here, so that begin-
1124+
// generator stubs can claim they produce a constructor().
1125+
set(instr.output, .constructor())
11221126
case .endClassDefinition:
11231127
let (instanceType, classDefinition) = dynamicObjectGroupManager.finalizeClass()
11241128
set(classDefinition.output, classDefinition.objectGroup.instanceType + .constructor(classDefinition.constructorParameters => instanceType))

0 commit comments

Comments
 (0)