WeighNodes.java revision 953:221a84ef44c0
1/* 2 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26package jdk.nashorn.internal.codegen; 27 28import java.util.List; 29import java.util.Map; 30import jdk.nashorn.internal.ir.AccessNode; 31import jdk.nashorn.internal.ir.BinaryNode; 32import jdk.nashorn.internal.ir.Block; 33import jdk.nashorn.internal.ir.BreakNode; 34import jdk.nashorn.internal.ir.CallNode; 35import jdk.nashorn.internal.ir.CatchNode; 36import jdk.nashorn.internal.ir.ContinueNode; 37import jdk.nashorn.internal.ir.ExpressionStatement; 38import jdk.nashorn.internal.ir.ForNode; 39import jdk.nashorn.internal.ir.FunctionNode; 40import jdk.nashorn.internal.ir.IdentNode; 41import jdk.nashorn.internal.ir.IfNode; 42import jdk.nashorn.internal.ir.IndexNode; 43import jdk.nashorn.internal.ir.LexicalContext; 44import jdk.nashorn.internal.ir.LiteralNode; 45import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode; 46import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode.ArrayUnit; 47import jdk.nashorn.internal.ir.Node; 48import jdk.nashorn.internal.ir.PropertyNode; 49import jdk.nashorn.internal.ir.ReturnNode; 50import jdk.nashorn.internal.ir.RuntimeNode; 51import jdk.nashorn.internal.ir.SplitNode; 52import jdk.nashorn.internal.ir.SwitchNode; 53import jdk.nashorn.internal.ir.ThrowNode; 54import jdk.nashorn.internal.ir.TryNode; 55import jdk.nashorn.internal.ir.UnaryNode; 56import jdk.nashorn.internal.ir.VarNode; 57import jdk.nashorn.internal.ir.WhileNode; 58import jdk.nashorn.internal.ir.WithNode; 59import jdk.nashorn.internal.ir.visitor.NodeOperatorVisitor; 60 61 62/** 63 * Computes the "byte code" weight of an AST segment. This is used 64 * for Splitting too large class files 65 */ 66final class WeighNodes extends NodeOperatorVisitor<LexicalContext> { 67 /* 68 * Weight constants. 69 */ 70 static final long FUNCTION_WEIGHT = 40; 71 static final long AASTORE_WEIGHT = 2; 72 static final long ACCESS_WEIGHT = 4; 73 static final long ADD_WEIGHT = 10; 74 static final long BREAK_WEIGHT = 1; 75 static final long CALL_WEIGHT = 10; 76 static final long CATCH_WEIGHT = 10; 77 static final long COMPARE_WEIGHT = 6; 78 static final long CONTINUE_WEIGHT = 1; 79 static final long IF_WEIGHT = 2; 80 static final long LITERAL_WEIGHT = 10; 81 static final long LOOP_WEIGHT = 4; 82 static final long NEW_WEIGHT = 6; 83 static final long FUNC_EXPR_WEIGHT = 20; 84 static final long RETURN_WEIGHT = 2; 85 static final long SPLIT_WEIGHT = 40; 86 static final long SWITCH_WEIGHT = 8; 87 static final long THROW_WEIGHT = 2; 88 static final long VAR_WEIGHT = 40; 89 static final long WITH_WEIGHT = 8; 90 91 /** Accumulated weight. */ 92 private long weight; 93 94 /** Optional cache for weight of block nodes. */ 95 private final Map<Node, Long> weightCache; 96 97 private final FunctionNode topFunction; 98 99 /** 100 * Constructor 101 * 102 * @param weightCache cache of already calculated block weights 103 */ 104 private WeighNodes(final FunctionNode topFunction, final Map<Node, Long> weightCache) { 105 super(new LexicalContext()); 106 this.topFunction = topFunction; 107 this.weightCache = weightCache; 108 } 109 110 static long weigh(final Node node) { 111 return weigh(node, null); 112 } 113 114 static long weigh(final Node node, final Map<Node, Long> weightCache) { 115 final WeighNodes weighNodes = new WeighNodes(node instanceof FunctionNode ? (FunctionNode)node : null, weightCache); 116 node.accept(weighNodes); 117 return weighNodes.weight; 118 } 119 120 @Override 121 public Node leaveAccessNode(final AccessNode accessNode) { 122 weight += ACCESS_WEIGHT; 123 return accessNode; 124 } 125 126 @Override 127 public boolean enterBlock(final Block block) { 128 if (weightCache != null && weightCache.containsKey(block)) { 129 weight += weightCache.get(block); 130 return false; 131 } 132 133 return true; 134 } 135 136 @Override 137 public Node leaveBreakNode(final BreakNode breakNode) { 138 weight += BREAK_WEIGHT; 139 return breakNode; 140 } 141 142 @Override 143 public Node leaveCallNode(final CallNode callNode) { 144 weight += CALL_WEIGHT; 145 return callNode; 146 } 147 148 @Override 149 public Node leaveCatchNode(final CatchNode catchNode) { 150 weight += CATCH_WEIGHT; 151 return catchNode; 152 } 153 154 @Override 155 public Node leaveContinueNode(final ContinueNode continueNode) { 156 weight += CONTINUE_WEIGHT; 157 return continueNode; 158 } 159 160 @Override 161 public Node leaveExpressionStatement(final ExpressionStatement expressionStatement) { 162 return expressionStatement; 163 } 164 165 @Override 166 public Node leaveForNode(final ForNode forNode) { 167 weight += LOOP_WEIGHT; 168 return forNode; 169 } 170 171 @Override 172 public boolean enterFunctionNode(final FunctionNode functionNode) { 173 if (functionNode == topFunction) { 174 // the function being weighted; descend into its statements 175 return true; 176 } 177 // just a reference to inner function from outer function 178 weight += FUNC_EXPR_WEIGHT; 179 return false; 180 } 181 182 @Override 183 public Node leaveIdentNode(final IdentNode identNode) { 184 weight += ACCESS_WEIGHT + identNode.getName().length() * 2; 185 return identNode; 186 } 187 188 @Override 189 public Node leaveIfNode(final IfNode ifNode) { 190 weight += IF_WEIGHT; 191 return ifNode; 192 } 193 194 @Override 195 public Node leaveIndexNode(final IndexNode indexNode) { 196 weight += ACCESS_WEIGHT; 197 return indexNode; 198 } 199 200 @SuppressWarnings("rawtypes") 201 @Override 202 public boolean enterLiteralNode(final LiteralNode literalNode) { 203 weight += LITERAL_WEIGHT; 204 205 if (literalNode instanceof ArrayLiteralNode) { 206 final ArrayLiteralNode arrayLiteralNode = (ArrayLiteralNode)literalNode; 207 final Node[] value = arrayLiteralNode.getValue(); 208 final int[] postsets = arrayLiteralNode.getPostsets(); 209 final List<ArrayUnit> units = arrayLiteralNode.getUnits(); 210 211 if (units == null) { 212 for (final int postset : postsets) { 213 weight += AASTORE_WEIGHT; 214 final Node element = value[postset]; 215 216 if (element != null) { 217 element.accept(this); 218 } 219 } 220 } 221 222 return false; 223 } 224 225 return true; 226 } 227 228 @Override 229 public Node leavePropertyNode(final PropertyNode propertyNode) { 230 weight += LITERAL_WEIGHT; 231 return propertyNode; 232 } 233 234 @Override 235 public Node leaveReturnNode(final ReturnNode returnNode) { 236 weight += RETURN_WEIGHT; 237 return returnNode; 238 } 239 240 @Override 241 public Node leaveRuntimeNode(final RuntimeNode runtimeNode) { 242 weight += CALL_WEIGHT; 243 return runtimeNode; 244 } 245 246 @Override 247 public boolean enterSplitNode(final SplitNode splitNode) { 248 weight += SPLIT_WEIGHT; 249 return false; 250 } 251 252 @Override 253 public Node leaveSwitchNode(final SwitchNode switchNode) { 254 weight += SWITCH_WEIGHT; 255 return switchNode; 256 } 257 258 @Override 259 public Node leaveThrowNode(final ThrowNode throwNode) { 260 weight += THROW_WEIGHT; 261 return throwNode; 262 } 263 264 @Override 265 public Node leaveTryNode(final TryNode tryNode) { 266 weight += THROW_WEIGHT; 267 return tryNode; 268 } 269 270 @Override 271 public Node leaveVarNode(final VarNode varNode) { 272 weight += VAR_WEIGHT; 273 return varNode; 274 } 275 276 @Override 277 public Node leaveWhileNode(final WhileNode whileNode) { 278 weight += LOOP_WEIGHT; 279 return whileNode; 280 } 281 282 @Override 283 public Node leaveWithNode(final WithNode withNode) { 284 weight += WITH_WEIGHT; 285 return withNode; 286 } 287 288 @Override 289 public Node leaveADD(final UnaryNode unaryNode) { 290 return unaryNodeWeight(unaryNode); 291 } 292 293 @Override 294 public Node leaveBIT_NOT(final UnaryNode unaryNode) { 295 return unaryNodeWeight(unaryNode); 296 } 297 298 @Override 299 public Node leaveDECINC(final UnaryNode unaryNode) { 300 return unaryNodeWeight(unaryNode); 301 } 302 303 @Override 304 public Node leaveDELETE(final UnaryNode unaryNode) { 305 return runtimeNodeWeight(unaryNode); 306 } 307 308 @Override 309 public Node leaveNEW(final UnaryNode unaryNode) { 310 weight += NEW_WEIGHT; 311 return unaryNode; 312 } 313 314 @Override 315 public Node leaveNOT(final UnaryNode unaryNode) { 316 return unaryNodeWeight(unaryNode); 317 } 318 319 @Override 320 public Node leaveSUB(final UnaryNode unaryNode) { 321 return unaryNodeWeight(unaryNode); 322 } 323 324 @Override 325 public Node leaveTYPEOF(final UnaryNode unaryNode) { 326 return runtimeNodeWeight(unaryNode); 327 } 328 329 @Override 330 public Node leaveVOID(final UnaryNode unaryNode) { 331 return unaryNodeWeight(unaryNode); 332 } 333 334 @Override 335 public Node leaveADD(final BinaryNode binaryNode) { 336 weight += ADD_WEIGHT; 337 return binaryNode; 338 } 339 340 @Override 341 public Node leaveAND(final BinaryNode binaryNode) { 342 return binaryNodeWeight(binaryNode); 343 } 344 345 @Override 346 public Node leaveASSIGN(final BinaryNode binaryNode) { 347 return binaryNodeWeight(binaryNode); 348 } 349 350 @Override 351 public Node leaveASSIGN_ADD(final BinaryNode binaryNode) { 352 weight += ADD_WEIGHT; 353 return binaryNode; 354 } 355 356 @Override 357 public Node leaveASSIGN_BIT_AND(final BinaryNode binaryNode) { 358 return binaryNodeWeight(binaryNode); 359 } 360 361 @Override 362 public Node leaveASSIGN_BIT_OR(final BinaryNode binaryNode) { 363 return binaryNodeWeight(binaryNode); 364 } 365 366 @Override 367 public Node leaveASSIGN_BIT_XOR(final BinaryNode binaryNode) { 368 return binaryNodeWeight(binaryNode); 369 } 370 371 @Override 372 public Node leaveASSIGN_DIV(final BinaryNode binaryNode) { 373 return binaryNodeWeight(binaryNode); 374 } 375 376 @Override 377 public Node leaveASSIGN_MOD(final BinaryNode binaryNode) { 378 return binaryNodeWeight(binaryNode); 379 } 380 381 @Override 382 public Node leaveASSIGN_MUL(final BinaryNode binaryNode) { 383 return binaryNodeWeight(binaryNode); 384 } 385 386 @Override 387 public Node leaveASSIGN_SAR(final BinaryNode binaryNode) { 388 return binaryNodeWeight(binaryNode); 389 } 390 391 @Override 392 public Node leaveASSIGN_SHL(final BinaryNode binaryNode) { 393 return binaryNodeWeight(binaryNode); 394 } 395 396 @Override 397 public Node leaveASSIGN_SHR(final BinaryNode binaryNode) { 398 return binaryNodeWeight(binaryNode); 399 } 400 401 @Override 402 public Node leaveASSIGN_SUB(final BinaryNode binaryNode) { 403 return binaryNodeWeight(binaryNode); 404 } 405 406 @Override 407 public Node leaveBIND(final BinaryNode binaryNode) { 408 return binaryNodeWeight(binaryNode); 409 } 410 411 @Override 412 public Node leaveBIT_AND(final BinaryNode binaryNode) { 413 return binaryNodeWeight(binaryNode); 414 } 415 416 @Override 417 public Node leaveBIT_OR(final BinaryNode binaryNode) { 418 return binaryNodeWeight(binaryNode); 419 } 420 421 @Override 422 public Node leaveBIT_XOR(final BinaryNode binaryNode) { 423 return binaryNodeWeight(binaryNode); 424 } 425 426 @Override 427 public Node leaveCOMMALEFT(final BinaryNode binaryNode) { 428 return binaryNodeWeight(binaryNode); 429 } 430 431 @Override 432 public Node leaveCOMMARIGHT(final BinaryNode binaryNode) { 433 return binaryNodeWeight(binaryNode); 434 } 435 436 @Override 437 public Node leaveDIV(final BinaryNode binaryNode) { 438 return binaryNodeWeight(binaryNode); 439 } 440 441 @Override 442 public Node leaveEQ(final BinaryNode binaryNode) { 443 return compareWeight(binaryNode); 444 } 445 446 @Override 447 public Node leaveEQ_STRICT(final BinaryNode binaryNode) { 448 return compareWeight(binaryNode); 449 } 450 451 @Override 452 public Node leaveGE(final BinaryNode binaryNode) { 453 return compareWeight(binaryNode); 454 } 455 456 @Override 457 public Node leaveGT(final BinaryNode binaryNode) { 458 return compareWeight(binaryNode); 459 } 460 461 @Override 462 public Node leaveIN(final BinaryNode binaryNode) { 463 weight += CALL_WEIGHT; 464 return binaryNode; 465 } 466 467 @Override 468 public Node leaveINSTANCEOF(final BinaryNode binaryNode) { 469 weight += CALL_WEIGHT; 470 return binaryNode; 471 } 472 473 @Override 474 public Node leaveLE(final BinaryNode binaryNode) { 475 return compareWeight(binaryNode); 476 } 477 478 @Override 479 public Node leaveLT(final BinaryNode binaryNode) { 480 return compareWeight(binaryNode); 481 } 482 483 @Override 484 public Node leaveMOD(final BinaryNode binaryNode) { 485 return binaryNodeWeight(binaryNode); 486 } 487 488 @Override 489 public Node leaveMUL(final BinaryNode binaryNode) { 490 return binaryNodeWeight(binaryNode); 491 } 492 493 @Override 494 public Node leaveNE(final BinaryNode binaryNode) { 495 return compareWeight(binaryNode); 496 } 497 498 @Override 499 public Node leaveNE_STRICT(final BinaryNode binaryNode) { 500 return compareWeight(binaryNode); 501 } 502 503 @Override 504 public Node leaveOR(final BinaryNode binaryNode) { 505 return binaryNodeWeight(binaryNode); 506 } 507 508 @Override 509 public Node leaveSAR(final BinaryNode binaryNode) { 510 return binaryNodeWeight(binaryNode); 511 } 512 513 @Override 514 public Node leaveSHL(final BinaryNode binaryNode) { 515 return binaryNodeWeight(binaryNode); 516 } 517 518 @Override 519 public Node leaveSHR(final BinaryNode binaryNode) { 520 return binaryNodeWeight(binaryNode); 521 } 522 523 @Override 524 public Node leaveSUB(final BinaryNode binaryNode) { 525 return binaryNodeWeight(binaryNode); 526 } 527 528 private Node unaryNodeWeight(final UnaryNode unaryNode) { 529 weight += 1; 530 return unaryNode; 531 } 532 533 private Node binaryNodeWeight(final BinaryNode binaryNode) { 534 weight += 1; 535 return binaryNode; 536 } 537 538 private Node runtimeNodeWeight(final UnaryNode unaryNode) { 539 weight += CALL_WEIGHT; 540 return unaryNode; 541 } 542 543 private Node compareWeight(final BinaryNode binaryNode) { 544 weight += COMPARE_WEIGHT; 545 return binaryNode; 546 } 547} 548