@@ -113,7 +113,7 @@ class CodegenContext {
113
113
val idx = references.length
114
114
references += obj
115
115
val clsName = Option (className).getOrElse(obj.getClass.getName)
116
- addMutableState(clsName, term, s " $term = ( $clsName) references[ $idx]; " )
116
+ addMutableState(clsName, term, s " this. $term = ( $clsName) references[ $idx]; " )
117
117
term
118
118
}
119
119
@@ -202,6 +202,16 @@ class CodegenContext {
202
202
partitionInitializationStatements.mkString(" \n " )
203
203
}
204
204
205
+ /**
206
+ * Holding all the functions those will be added into generated class.
207
+ */
208
+ val addedFunctions : mutable.Map [String , String ] =
209
+ mutable.Map .empty[String , String ]
210
+
211
+ def addNewFunction (funcName : String , funcCode : String ): Unit = {
212
+ addedFunctions += ((funcName, funcCode))
213
+ }
214
+
205
215
/**
206
216
* Holds expressions that are equivalent. Used to perform subexpression elimination
207
217
* during codegen.
@@ -223,118 +233,10 @@ class CodegenContext {
223
233
// The collection of sub-expression result resetting methods that need to be called on each row.
224
234
val subexprFunctions = mutable.ArrayBuffer .empty[String ]
225
235
226
- private val outerClassName = " OuterClass"
227
-
228
- /**
229
- * Holds the class and instance names to be generated, where `OuterClass` is a placeholder
230
- * standing for whichever class is generated as the outermost class and which will contain any
231
- * nested sub-classes. All other classes and instance names in this list will represent private,
232
- * nested sub-classes.
233
- */
234
- private val classes : mutable.ListBuffer [(String , String )] =
235
- mutable.ListBuffer [(String , String )](outerClassName -> null )
236
-
237
- // A map holding the current size in bytes of each class to be generated.
238
- private val classSize : mutable.Map [String , Int ] =
239
- mutable.Map [String , Int ](outerClassName -> 0 )
240
-
241
- // Nested maps holding function names and their code belonging to each class.
242
- private val classFunctions : mutable.Map [String , mutable.Map [String , String ]] =
243
- mutable.Map (outerClassName -> mutable.Map .empty[String , String ])
244
-
245
- // Returns the size of the most recently added class.
246
- private def currClassSize (): Int = classSize(classes.head._1)
247
-
248
- // Returns the class name and instance name for the most recently added class.
249
- private def currClass (): (String , String ) = classes.head
250
-
251
- // Adds a new class. Requires the class' name, and its instance name.
252
- private def addClass (className : String , classInstance : String ): Unit = {
253
- classes.prepend(className -> classInstance)
254
- classSize += className -> 0
255
- classFunctions += className -> mutable.Map .empty[String , String ]
236
+ def declareAddedFunctions (): String = {
237
+ addedFunctions.map { case (funcName, funcCode) => funcCode }.mkString(" \n " )
256
238
}
257
239
258
- /**
259
- * Adds a function to the generated class. If the code for the `OuterClass` grows too large, the
260
- * function will be inlined into a new private, nested class, and a instance-qualified name for
261
- * the function will be returned. Otherwise, the function will be inined to the `OuterClass` the
262
- * simple `funcName` will be returned.
263
- *
264
- * @param funcName the class-unqualified name of the function
265
- * @param funcCode the body of the function
266
- * @param inlineToOuterClass whether the given code must be inlined to the `OuterClass`. This
267
- * can be necessary when a function is declared outside of the context
268
- * it is eventually referenced and a returned qualified function name
269
- * cannot otherwise be accessed.
270
- * @return the name of the function, qualified by class if it will be inlined to a private,
271
- * nested sub-class
272
- */
273
- def addNewFunction (
274
- funcName : String ,
275
- funcCode : String ,
276
- inlineToOuterClass : Boolean = false ): String = {
277
- // The number of named constants that can exist in the class is limited by the Constant Pool
278
- // limit, 65,536. We cannot know how many constants will be inserted for a class, so we use a
279
- // threshold of 1600k bytes to determine when a function should be inlined to a private, nested
280
- // sub-class.
281
- val (className, classInstance) = if (inlineToOuterClass) {
282
- outerClassName -> " "
283
- } else if (currClassSize > 1600000 ) {
284
- val className = freshName(" NestedClass" )
285
- val classInstance = freshName(" nestedClassInstance" )
286
-
287
- addClass(className, classInstance)
288
-
289
- className -> classInstance
290
- } else {
291
- currClass()
292
- }
293
-
294
- classSize(className) += funcCode.length
295
- classFunctions(className) += funcName -> funcCode
296
-
297
- if (className == outerClassName) {
298
- funcName
299
- } else {
300
-
301
- s " $classInstance. $funcName"
302
- }
303
- }
304
-
305
- /**
306
- * Instantiates all nested, private sub-classes as objects to the `OuterClass`
307
- */
308
- private [sql] def initNestedClasses (): String = {
309
- // Nested, private sub-classes have no mutable state (though they do reference the outer class'
310
- // mutable state), so we declare and initialize them inline to the OuterClass.
311
- classes.filter(_._1 != outerClassName).map {
312
- case (className, classInstance) =>
313
- s " private $className $classInstance = new $className(); "
314
- }.mkString(" \n " )
315
- }
316
-
317
- /**
318
- * Declares all function code that should be inlined to the `OuterClass`.
319
- */
320
- private [sql] def declareAddedFunctions (): String = {
321
- classFunctions(outerClassName).values.mkString(" \n " )
322
- }
323
-
324
- /**
325
- * Declares all nested, private sub-classes and the function code that should be inlined to them.
326
- */
327
- private [sql] def declareNestedClasses (): String = {
328
- classFunctions.filterKeys(_ != outerClassName).map {
329
- case (className, functions) =>
330
- s """
331
- |private class $className {
332
- | ${functions.values.mkString(" \n " )}
333
- |}
334
- """ .stripMargin
335
- }
336
- }.mkString(" \n " )
337
-
338
240
final val JAVA_BOOLEAN = " boolean"
339
241
final val JAVA_BYTE = " byte"
340
242
final val JAVA_SHORT = " short"
@@ -654,7 +556,8 @@ class CodegenContext {
654
556
return 0;
655
557
}
656
558
"""
657
- s " ${addNewFunction(compareFunc, funcCode)}( $c1, $c2) "
559
+ addNewFunction(compareFunc, funcCode)
560
+ s " this. $compareFunc( $c1, $c2) "
658
561
case schema : StructType =>
659
562
val comparisons = GenerateOrdering .genComparisons(this , schema)
660
563
val compareFunc = freshName(" compareStruct" )
@@ -670,7 +573,8 @@ class CodegenContext {
670
573
return 0;
671
574
}
672
575
"""
673
- s " ${addNewFunction(compareFunc, funcCode)}( $c1, $c2) "
576
+ addNewFunction(compareFunc, funcCode)
577
+ s " this. $compareFunc( $c1, $c2) "
674
578
case other if other.isInstanceOf [AtomicType ] => s " $c1.compare( $c2) "
675
579
case udt : UserDefinedType [_] => genComp(udt.sqlType, c1, c2)
676
580
case _ =>
@@ -785,6 +689,7 @@ class CodegenContext {
785
689
|}
786
690
""" .stripMargin
787
691
addNewFunction(name, code)
692
+ name
788
693
}
789
694
790
695
foldFunctions(functions.map(name => s " $name( ${arguments.map(_._2).mkString(" , " )}) " ))
@@ -868,6 +773,8 @@ class CodegenContext {
868
773
|}
869
774
""" .stripMargin
870
775
776
+ addNewFunction(fnName, fn)
777
+
871
778
// Add a state and a mapping of the common subexpressions that are associate with this
872
779
// state. Adding this expression to subExprEliminationExprMap means it will call `fn`
873
780
// when it is code generated. This decision should be a cost based one.
@@ -885,7 +792,7 @@ class CodegenContext {
885
792
addMutableState(javaType(expr.dataType), value,
886
793
s " $value = ${defaultValue(expr.dataType)}; " )
887
794
888
- subexprFunctions += s " ${addNewFunction( fnName, fn)} ( $INPUT_ROW); "
795
+ subexprFunctions += s " $fnName( $INPUT_ROW); "
889
796
val state = SubExprEliminationState (isNull, value)
890
797
e.foreach(subExprEliminationExprs.put(_, state))
891
798
}
0 commit comments