Tue, 23 Nov 2010 13:22:55 -0800
6989984: Use standard include model for Hospot
Summary: Replaced MakeDeps and the includeDB files with more standardized solutions.
Reviewed-by: coleenp, kvn, kamg
twisti@2047 | 1 | /* |
stefank@2314 | 2 | * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. |
twisti@2047 | 3 | * Copyright 2009 Red Hat, Inc. |
twisti@2047 | 4 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
twisti@2047 | 5 | * |
twisti@2047 | 6 | * This code is free software; you can redistribute it and/or modify it |
twisti@2047 | 7 | * under the terms of the GNU General Public License version 2 only, as |
twisti@2047 | 8 | * published by the Free Software Foundation. |
twisti@2047 | 9 | * |
twisti@2047 | 10 | * This code is distributed in the hope that it will be useful, but WITHOUT |
twisti@2047 | 11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
twisti@2047 | 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
twisti@2047 | 13 | * version 2 for more details (a copy is included in the LICENSE file that |
twisti@2047 | 14 | * accompanied this code). |
twisti@2047 | 15 | * |
twisti@2047 | 16 | * You should have received a copy of the GNU General Public License version |
twisti@2047 | 17 | * 2 along with this work; if not, write to the Free Software Foundation, |
twisti@2047 | 18 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
twisti@2047 | 19 | * |
twisti@2047 | 20 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
twisti@2047 | 21 | * or visit www.oracle.com if you need additional information or have any |
twisti@2047 | 22 | * questions. |
twisti@2047 | 23 | * |
twisti@2047 | 24 | */ |
twisti@2047 | 25 | |
stefank@2314 | 26 | #include "precompiled.hpp" |
stefank@2314 | 27 | #include "ci/ciField.hpp" |
stefank@2314 | 28 | #include "ci/ciMethod.hpp" |
stefank@2314 | 29 | #include "ci/ciStreams.hpp" |
stefank@2314 | 30 | #include "interpreter/bytecodes.hpp" |
stefank@2314 | 31 | #include "memory/allocation.hpp" |
stefank@2314 | 32 | #include "shark/sharkBlock.hpp" |
stefank@2314 | 33 | #include "shark/sharkConstant.hpp" |
stefank@2314 | 34 | #include "shark/sharkInliner.hpp" |
stefank@2314 | 35 | #include "shark/sharkIntrinsics.hpp" |
stefank@2314 | 36 | #include "shark/sharkState.hpp" |
stefank@2314 | 37 | #include "shark/sharkValue.hpp" |
stefank@2314 | 38 | #include "shark/shark_globals.hpp" |
twisti@2047 | 39 | |
twisti@2047 | 40 | using namespace llvm; |
twisti@2047 | 41 | |
twisti@2047 | 42 | class SharkInlineBlock : public SharkBlock { |
twisti@2047 | 43 | public: |
twisti@2047 | 44 | SharkInlineBlock(ciMethod* target, SharkState* state) |
twisti@2047 | 45 | : SharkBlock(state, target), |
twisti@2047 | 46 | _outer_state(state), |
twisti@2047 | 47 | _entry_state(new SharkState(this)) { |
twisti@2047 | 48 | for (int i = target->max_locals() - 1; i >= 0; i--) { |
twisti@2047 | 49 | SharkValue *value = NULL; |
twisti@2047 | 50 | if (i < target->arg_size()) |
twisti@2047 | 51 | value = outer_state()->pop(); |
twisti@2047 | 52 | entry_state()->set_local(i, value); |
twisti@2047 | 53 | } |
twisti@2047 | 54 | } |
twisti@2047 | 55 | |
twisti@2047 | 56 | private: |
twisti@2047 | 57 | SharkState* _outer_state; |
twisti@2047 | 58 | SharkState* _entry_state; |
twisti@2047 | 59 | |
twisti@2047 | 60 | private: |
twisti@2047 | 61 | SharkState* outer_state() { |
twisti@2047 | 62 | return _outer_state; |
twisti@2047 | 63 | } |
twisti@2047 | 64 | SharkState* entry_state() { |
twisti@2047 | 65 | return _entry_state; |
twisti@2047 | 66 | } |
twisti@2047 | 67 | |
twisti@2047 | 68 | public: |
twisti@2047 | 69 | void emit_IR() { |
twisti@2047 | 70 | parse_bytecode(0, target()->code_size()); |
twisti@2047 | 71 | } |
twisti@2047 | 72 | |
twisti@2047 | 73 | private: |
twisti@2047 | 74 | void do_return(BasicType type) { |
twisti@2047 | 75 | if (type != T_VOID) { |
twisti@2047 | 76 | SharkValue *result = pop_result(type); |
twisti@2047 | 77 | outer_state()->push(result); |
twisti@2047 | 78 | if (result->is_two_word()) |
twisti@2047 | 79 | outer_state()->push(NULL); |
twisti@2047 | 80 | } |
twisti@2047 | 81 | } |
twisti@2047 | 82 | }; |
twisti@2047 | 83 | |
twisti@2047 | 84 | class SharkInlinerHelper : public StackObj { |
twisti@2047 | 85 | public: |
twisti@2047 | 86 | SharkInlinerHelper(ciMethod* target, SharkState* entry_state) |
twisti@2047 | 87 | : _target(target), |
twisti@2047 | 88 | _entry_state(entry_state), |
twisti@2047 | 89 | _iter(target) {} |
twisti@2047 | 90 | |
twisti@2047 | 91 | private: |
twisti@2047 | 92 | ciBytecodeStream _iter; |
twisti@2047 | 93 | SharkState* _entry_state; |
twisti@2047 | 94 | ciMethod* _target; |
twisti@2047 | 95 | |
twisti@2047 | 96 | public: |
twisti@2047 | 97 | ciBytecodeStream* iter() { |
twisti@2047 | 98 | return &_iter; |
twisti@2047 | 99 | } |
twisti@2047 | 100 | SharkState* entry_state() const { |
twisti@2047 | 101 | return _entry_state; |
twisti@2047 | 102 | } |
twisti@2047 | 103 | ciMethod* target() const { |
twisti@2047 | 104 | return _target; |
twisti@2047 | 105 | } |
twisti@2047 | 106 | |
twisti@2047 | 107 | public: |
twisti@2047 | 108 | Bytecodes::Code bc() { |
twisti@2047 | 109 | return iter()->cur_bc(); |
twisti@2047 | 110 | } |
twisti@2047 | 111 | int max_locals() const { |
twisti@2047 | 112 | return target()->max_locals(); |
twisti@2047 | 113 | } |
twisti@2047 | 114 | int max_stack() const { |
twisti@2047 | 115 | return target()->max_stack(); |
twisti@2047 | 116 | } |
twisti@2047 | 117 | |
twisti@2047 | 118 | // Inlinability check |
twisti@2047 | 119 | public: |
twisti@2047 | 120 | bool is_inlinable(); |
twisti@2047 | 121 | |
twisti@2047 | 122 | private: |
twisti@2047 | 123 | void initialize_for_check(); |
twisti@2047 | 124 | |
twisti@2047 | 125 | bool do_getstatic() { |
twisti@2047 | 126 | return do_field_access(true, false); |
twisti@2047 | 127 | } |
twisti@2047 | 128 | bool do_getfield() { |
twisti@2047 | 129 | return do_field_access(true, true); |
twisti@2047 | 130 | } |
twisti@2047 | 131 | bool do_putfield() { |
twisti@2047 | 132 | return do_field_access(false, true); |
twisti@2047 | 133 | } |
twisti@2047 | 134 | bool do_field_access(bool is_get, bool is_field); |
twisti@2047 | 135 | |
twisti@2047 | 136 | // Local variables for inlinability check |
twisti@2047 | 137 | private: |
twisti@2047 | 138 | bool* _locals; |
twisti@2047 | 139 | |
twisti@2047 | 140 | public: |
twisti@2047 | 141 | bool* local_addr(int index) const { |
twisti@2047 | 142 | assert(index >= 0 && index < max_locals(), "bad local variable index"); |
twisti@2047 | 143 | return &_locals[index]; |
twisti@2047 | 144 | } |
twisti@2047 | 145 | bool local(int index) const { |
twisti@2047 | 146 | return *local_addr(index); |
twisti@2047 | 147 | } |
twisti@2047 | 148 | void set_local(int index, bool value) { |
twisti@2047 | 149 | *local_addr(index) = value; |
twisti@2047 | 150 | } |
twisti@2047 | 151 | |
twisti@2047 | 152 | // Expression stack for inlinability check |
twisti@2047 | 153 | private: |
twisti@2047 | 154 | bool* _stack; |
twisti@2047 | 155 | bool* _sp; |
twisti@2047 | 156 | |
twisti@2047 | 157 | public: |
twisti@2047 | 158 | int stack_depth() const { |
twisti@2047 | 159 | return _sp - _stack; |
twisti@2047 | 160 | } |
twisti@2047 | 161 | bool* stack_addr(int slot) const { |
twisti@2047 | 162 | assert(slot >= 0 && slot < stack_depth(), "bad stack slot"); |
twisti@2047 | 163 | return &_sp[-(slot + 1)]; |
twisti@2047 | 164 | } |
twisti@2047 | 165 | void push(bool value) { |
twisti@2047 | 166 | assert(stack_depth() < max_stack(), "stack overrun"); |
twisti@2047 | 167 | *(_sp++) = value; |
twisti@2047 | 168 | } |
twisti@2047 | 169 | bool pop() { |
twisti@2047 | 170 | assert(stack_depth() > 0, "stack underrun"); |
twisti@2047 | 171 | return *(--_sp); |
twisti@2047 | 172 | } |
twisti@2047 | 173 | |
twisti@2047 | 174 | // Methods for two-word locals |
twisti@2047 | 175 | public: |
twisti@2047 | 176 | void push_pair_local(int index) { |
twisti@2047 | 177 | push(local(index)); |
twisti@2047 | 178 | push(local(index + 1)); |
twisti@2047 | 179 | } |
twisti@2047 | 180 | void pop_pair_local(int index) { |
twisti@2047 | 181 | set_local(index + 1, pop()); |
twisti@2047 | 182 | set_local(index, pop()); |
twisti@2047 | 183 | } |
twisti@2047 | 184 | |
twisti@2047 | 185 | // Code generation |
twisti@2047 | 186 | public: |
twisti@2047 | 187 | void do_inline() { |
twisti@2047 | 188 | (new SharkInlineBlock(target(), entry_state()))->emit_IR(); |
twisti@2047 | 189 | } |
twisti@2047 | 190 | }; |
twisti@2047 | 191 | |
twisti@2047 | 192 | // Quick checks so we can bail out before doing too much |
twisti@2047 | 193 | bool SharkInliner::may_be_inlinable(ciMethod *target) { |
twisti@2047 | 194 | // We can't inline native methods |
twisti@2047 | 195 | if (target->is_native()) |
twisti@2047 | 196 | return false; |
twisti@2047 | 197 | |
twisti@2047 | 198 | // Not much point inlining abstract ones, and in any |
twisti@2047 | 199 | // case we'd need a stack frame to throw the exception |
twisti@2047 | 200 | if (target->is_abstract()) |
twisti@2047 | 201 | return false; |
twisti@2047 | 202 | |
twisti@2047 | 203 | // Don't inline anything huge |
twisti@2047 | 204 | if (target->code_size() > SharkMaxInlineSize) |
twisti@2047 | 205 | return false; |
twisti@2047 | 206 | |
twisti@2047 | 207 | // Monitors aren't allowed without a frame to put them in |
twisti@2047 | 208 | if (target->is_synchronized() || target->has_monitor_bytecodes()) |
twisti@2047 | 209 | return false; |
twisti@2047 | 210 | |
twisti@2047 | 211 | // We don't do control flow |
twisti@2047 | 212 | if (target->has_exception_handlers() || target->has_jsrs()) |
twisti@2047 | 213 | return false; |
twisti@2047 | 214 | |
twisti@2047 | 215 | // Don't try to inline constructors, as they must |
twisti@2047 | 216 | // eventually call Object.<init> which we can't inline. |
twisti@2047 | 217 | // Note that this catches <clinit> too, but why would |
twisti@2047 | 218 | // we be compiling that? |
twisti@2047 | 219 | if (target->is_initializer()) |
twisti@2047 | 220 | return false; |
twisti@2047 | 221 | |
twisti@2047 | 222 | // Mustn't inline Object.<init> |
twisti@2047 | 223 | // Should be caught by the above, but just in case... |
twisti@2047 | 224 | if (target->intrinsic_id() == vmIntrinsics::_Object_init) |
twisti@2047 | 225 | return false; |
twisti@2047 | 226 | |
twisti@2047 | 227 | return true; |
twisti@2047 | 228 | } |
twisti@2047 | 229 | |
twisti@2047 | 230 | // Full-on detailed check, for methods that pass the quick checks |
twisti@2047 | 231 | // Inlined methods have no stack frame, so we can't do anything |
twisti@2047 | 232 | // that would require one. This means no safepoints (and hence |
twisti@2047 | 233 | // no loops) and no VM calls. No VM calls means, amongst other |
twisti@2047 | 234 | // things, that no exceptions can be created, which means no null |
twisti@2047 | 235 | // checks or divide-by-zero checks are allowed. The lack of null |
twisti@2047 | 236 | // checks in particular would eliminate practically everything, |
twisti@2047 | 237 | // but we can get around that restriction by relying on the zero- |
twisti@2047 | 238 | // check eliminator to strip the checks. To do that, we need to |
twisti@2047 | 239 | // walk through the method, tracking which values are and are not |
twisti@2047 | 240 | // zero-checked. |
twisti@2047 | 241 | bool SharkInlinerHelper::is_inlinable() { |
twisti@2047 | 242 | ResourceMark rm; |
twisti@2047 | 243 | initialize_for_check(); |
twisti@2047 | 244 | |
twisti@2047 | 245 | SharkConstant *sc; |
twisti@2047 | 246 | bool a, b, c, d; |
twisti@2047 | 247 | |
twisti@2047 | 248 | iter()->reset_to_bci(0); |
twisti@2047 | 249 | while (iter()->next() != ciBytecodeStream::EOBC()) { |
twisti@2047 | 250 | switch (bc()) { |
twisti@2047 | 251 | case Bytecodes::_nop: |
twisti@2047 | 252 | break; |
twisti@2047 | 253 | |
twisti@2047 | 254 | case Bytecodes::_aconst_null: |
twisti@2047 | 255 | push(false); |
twisti@2047 | 256 | break; |
twisti@2047 | 257 | |
twisti@2047 | 258 | case Bytecodes::_iconst_0: |
twisti@2047 | 259 | push(false); |
twisti@2047 | 260 | break; |
twisti@2047 | 261 | case Bytecodes::_iconst_m1: |
twisti@2047 | 262 | case Bytecodes::_iconst_1: |
twisti@2047 | 263 | case Bytecodes::_iconst_2: |
twisti@2047 | 264 | case Bytecodes::_iconst_3: |
twisti@2047 | 265 | case Bytecodes::_iconst_4: |
twisti@2047 | 266 | case Bytecodes::_iconst_5: |
twisti@2047 | 267 | push(true); |
twisti@2047 | 268 | break; |
twisti@2047 | 269 | |
twisti@2047 | 270 | case Bytecodes::_lconst_0: |
twisti@2047 | 271 | push(false); |
twisti@2047 | 272 | push(false); |
twisti@2047 | 273 | break; |
twisti@2047 | 274 | case Bytecodes::_lconst_1: |
twisti@2047 | 275 | push(true); |
twisti@2047 | 276 | push(false); |
twisti@2047 | 277 | break; |
twisti@2047 | 278 | |
twisti@2047 | 279 | case Bytecodes::_fconst_0: |
twisti@2047 | 280 | case Bytecodes::_fconst_1: |
twisti@2047 | 281 | case Bytecodes::_fconst_2: |
twisti@2047 | 282 | push(false); |
twisti@2047 | 283 | break; |
twisti@2047 | 284 | |
twisti@2047 | 285 | case Bytecodes::_dconst_0: |
twisti@2047 | 286 | case Bytecodes::_dconst_1: |
twisti@2047 | 287 | push(false); |
twisti@2047 | 288 | push(false); |
twisti@2047 | 289 | break; |
twisti@2047 | 290 | |
twisti@2047 | 291 | case Bytecodes::_bipush: |
twisti@2047 | 292 | push(iter()->get_constant_u1() != 0); |
twisti@2047 | 293 | break; |
twisti@2047 | 294 | case Bytecodes::_sipush: |
twisti@2047 | 295 | push(iter()->get_constant_u2() != 0); |
twisti@2047 | 296 | break; |
twisti@2047 | 297 | |
twisti@2047 | 298 | case Bytecodes::_ldc: |
twisti@2047 | 299 | case Bytecodes::_ldc_w: |
twisti@2047 | 300 | case Bytecodes::_ldc2_w: |
twisti@2047 | 301 | sc = SharkConstant::for_ldc(iter()); |
twisti@2047 | 302 | if (!sc->is_loaded()) |
twisti@2047 | 303 | return false; |
twisti@2047 | 304 | push(sc->is_nonzero()); |
twisti@2047 | 305 | if (sc->is_two_word()) |
twisti@2047 | 306 | push(false); |
twisti@2047 | 307 | break; |
twisti@2047 | 308 | |
twisti@2047 | 309 | case Bytecodes::_iload_0: |
twisti@2047 | 310 | case Bytecodes::_fload_0: |
twisti@2047 | 311 | case Bytecodes::_aload_0: |
twisti@2047 | 312 | push(local(0)); |
twisti@2047 | 313 | break; |
twisti@2047 | 314 | case Bytecodes::_lload_0: |
twisti@2047 | 315 | case Bytecodes::_dload_0: |
twisti@2047 | 316 | push_pair_local(0); |
twisti@2047 | 317 | break; |
twisti@2047 | 318 | |
twisti@2047 | 319 | case Bytecodes::_iload_1: |
twisti@2047 | 320 | case Bytecodes::_fload_1: |
twisti@2047 | 321 | case Bytecodes::_aload_1: |
twisti@2047 | 322 | push(local(1)); |
twisti@2047 | 323 | break; |
twisti@2047 | 324 | case Bytecodes::_lload_1: |
twisti@2047 | 325 | case Bytecodes::_dload_1: |
twisti@2047 | 326 | push_pair_local(1); |
twisti@2047 | 327 | break; |
twisti@2047 | 328 | |
twisti@2047 | 329 | case Bytecodes::_iload_2: |
twisti@2047 | 330 | case Bytecodes::_fload_2: |
twisti@2047 | 331 | case Bytecodes::_aload_2: |
twisti@2047 | 332 | push(local(2)); |
twisti@2047 | 333 | break; |
twisti@2047 | 334 | case Bytecodes::_lload_2: |
twisti@2047 | 335 | case Bytecodes::_dload_2: |
twisti@2047 | 336 | push_pair_local(2); |
twisti@2047 | 337 | break; |
twisti@2047 | 338 | |
twisti@2047 | 339 | case Bytecodes::_iload_3: |
twisti@2047 | 340 | case Bytecodes::_fload_3: |
twisti@2047 | 341 | case Bytecodes::_aload_3: |
twisti@2047 | 342 | push(local(3)); |
twisti@2047 | 343 | break; |
twisti@2047 | 344 | case Bytecodes::_lload_3: |
twisti@2047 | 345 | case Bytecodes::_dload_3: |
twisti@2047 | 346 | push_pair_local(3); |
twisti@2047 | 347 | break; |
twisti@2047 | 348 | |
twisti@2047 | 349 | case Bytecodes::_iload: |
twisti@2047 | 350 | case Bytecodes::_fload: |
twisti@2047 | 351 | case Bytecodes::_aload: |
twisti@2047 | 352 | push(local(iter()->get_index())); |
twisti@2047 | 353 | break; |
twisti@2047 | 354 | case Bytecodes::_lload: |
twisti@2047 | 355 | case Bytecodes::_dload: |
twisti@2047 | 356 | push_pair_local(iter()->get_index()); |
twisti@2047 | 357 | break; |
twisti@2047 | 358 | |
twisti@2047 | 359 | case Bytecodes::_istore_0: |
twisti@2047 | 360 | case Bytecodes::_fstore_0: |
twisti@2047 | 361 | case Bytecodes::_astore_0: |
twisti@2047 | 362 | set_local(0, pop()); |
twisti@2047 | 363 | break; |
twisti@2047 | 364 | case Bytecodes::_lstore_0: |
twisti@2047 | 365 | case Bytecodes::_dstore_0: |
twisti@2047 | 366 | pop_pair_local(0); |
twisti@2047 | 367 | break; |
twisti@2047 | 368 | |
twisti@2047 | 369 | case Bytecodes::_istore_1: |
twisti@2047 | 370 | case Bytecodes::_fstore_1: |
twisti@2047 | 371 | case Bytecodes::_astore_1: |
twisti@2047 | 372 | set_local(1, pop()); |
twisti@2047 | 373 | break; |
twisti@2047 | 374 | case Bytecodes::_lstore_1: |
twisti@2047 | 375 | case Bytecodes::_dstore_1: |
twisti@2047 | 376 | pop_pair_local(1); |
twisti@2047 | 377 | break; |
twisti@2047 | 378 | |
twisti@2047 | 379 | case Bytecodes::_istore_2: |
twisti@2047 | 380 | case Bytecodes::_fstore_2: |
twisti@2047 | 381 | case Bytecodes::_astore_2: |
twisti@2047 | 382 | set_local(2, pop()); |
twisti@2047 | 383 | break; |
twisti@2047 | 384 | case Bytecodes::_lstore_2: |
twisti@2047 | 385 | case Bytecodes::_dstore_2: |
twisti@2047 | 386 | pop_pair_local(2); |
twisti@2047 | 387 | break; |
twisti@2047 | 388 | |
twisti@2047 | 389 | case Bytecodes::_istore_3: |
twisti@2047 | 390 | case Bytecodes::_fstore_3: |
twisti@2047 | 391 | case Bytecodes::_astore_3: |
twisti@2047 | 392 | set_local(3, pop()); |
twisti@2047 | 393 | break; |
twisti@2047 | 394 | case Bytecodes::_lstore_3: |
twisti@2047 | 395 | case Bytecodes::_dstore_3: |
twisti@2047 | 396 | pop_pair_local(3); |
twisti@2047 | 397 | break; |
twisti@2047 | 398 | |
twisti@2047 | 399 | case Bytecodes::_istore: |
twisti@2047 | 400 | case Bytecodes::_fstore: |
twisti@2047 | 401 | case Bytecodes::_astore: |
twisti@2047 | 402 | set_local(iter()->get_index(), pop()); |
twisti@2047 | 403 | break; |
twisti@2047 | 404 | case Bytecodes::_lstore: |
twisti@2047 | 405 | case Bytecodes::_dstore: |
twisti@2047 | 406 | pop_pair_local(iter()->get_index()); |
twisti@2047 | 407 | break; |
twisti@2047 | 408 | |
twisti@2047 | 409 | case Bytecodes::_pop: |
twisti@2047 | 410 | pop(); |
twisti@2047 | 411 | break; |
twisti@2047 | 412 | case Bytecodes::_pop2: |
twisti@2047 | 413 | pop(); |
twisti@2047 | 414 | pop(); |
twisti@2047 | 415 | break; |
twisti@2047 | 416 | case Bytecodes::_swap: |
twisti@2047 | 417 | a = pop(); |
twisti@2047 | 418 | b = pop(); |
twisti@2047 | 419 | push(a); |
twisti@2047 | 420 | push(b); |
twisti@2047 | 421 | break; |
twisti@2047 | 422 | case Bytecodes::_dup: |
twisti@2047 | 423 | a = pop(); |
twisti@2047 | 424 | push(a); |
twisti@2047 | 425 | push(a); |
twisti@2047 | 426 | break; |
twisti@2047 | 427 | case Bytecodes::_dup_x1: |
twisti@2047 | 428 | a = pop(); |
twisti@2047 | 429 | b = pop(); |
twisti@2047 | 430 | push(a); |
twisti@2047 | 431 | push(b); |
twisti@2047 | 432 | push(a); |
twisti@2047 | 433 | break; |
twisti@2047 | 434 | case Bytecodes::_dup_x2: |
twisti@2047 | 435 | a = pop(); |
twisti@2047 | 436 | b = pop(); |
twisti@2047 | 437 | c = pop(); |
twisti@2047 | 438 | push(a); |
twisti@2047 | 439 | push(c); |
twisti@2047 | 440 | push(b); |
twisti@2047 | 441 | push(a); |
twisti@2047 | 442 | break; |
twisti@2047 | 443 | case Bytecodes::_dup2: |
twisti@2047 | 444 | a = pop(); |
twisti@2047 | 445 | b = pop(); |
twisti@2047 | 446 | push(b); |
twisti@2047 | 447 | push(a); |
twisti@2047 | 448 | push(b); |
twisti@2047 | 449 | push(a); |
twisti@2047 | 450 | break; |
twisti@2047 | 451 | case Bytecodes::_dup2_x1: |
twisti@2047 | 452 | a = pop(); |
twisti@2047 | 453 | b = pop(); |
twisti@2047 | 454 | c = pop(); |
twisti@2047 | 455 | push(b); |
twisti@2047 | 456 | push(a); |
twisti@2047 | 457 | push(c); |
twisti@2047 | 458 | push(b); |
twisti@2047 | 459 | push(a); |
twisti@2047 | 460 | break; |
twisti@2047 | 461 | case Bytecodes::_dup2_x2: |
twisti@2047 | 462 | a = pop(); |
twisti@2047 | 463 | b = pop(); |
twisti@2047 | 464 | c = pop(); |
twisti@2047 | 465 | d = pop(); |
twisti@2047 | 466 | push(b); |
twisti@2047 | 467 | push(a); |
twisti@2047 | 468 | push(d); |
twisti@2047 | 469 | push(c); |
twisti@2047 | 470 | push(b); |
twisti@2047 | 471 | push(a); |
twisti@2047 | 472 | break; |
twisti@2047 | 473 | |
twisti@2047 | 474 | case Bytecodes::_getfield: |
twisti@2047 | 475 | if (!do_getfield()) |
twisti@2047 | 476 | return false; |
twisti@2047 | 477 | break; |
twisti@2047 | 478 | case Bytecodes::_getstatic: |
twisti@2047 | 479 | if (!do_getstatic()) |
twisti@2047 | 480 | return false; |
twisti@2047 | 481 | break; |
twisti@2047 | 482 | case Bytecodes::_putfield: |
twisti@2047 | 483 | if (!do_putfield()) |
twisti@2047 | 484 | return false; |
twisti@2047 | 485 | break; |
twisti@2047 | 486 | |
twisti@2047 | 487 | case Bytecodes::_iadd: |
twisti@2047 | 488 | case Bytecodes::_isub: |
twisti@2047 | 489 | case Bytecodes::_imul: |
twisti@2047 | 490 | case Bytecodes::_iand: |
twisti@2047 | 491 | case Bytecodes::_ixor: |
twisti@2047 | 492 | case Bytecodes::_ishl: |
twisti@2047 | 493 | case Bytecodes::_ishr: |
twisti@2047 | 494 | case Bytecodes::_iushr: |
twisti@2047 | 495 | pop(); |
twisti@2047 | 496 | pop(); |
twisti@2047 | 497 | push(false); |
twisti@2047 | 498 | break; |
twisti@2047 | 499 | case Bytecodes::_ior: |
twisti@2047 | 500 | a = pop(); |
twisti@2047 | 501 | b = pop(); |
twisti@2047 | 502 | push(a && b); |
twisti@2047 | 503 | break; |
twisti@2047 | 504 | case Bytecodes::_idiv: |
twisti@2047 | 505 | case Bytecodes::_irem: |
twisti@2047 | 506 | if (!pop()) |
twisti@2047 | 507 | return false; |
twisti@2047 | 508 | pop(); |
twisti@2047 | 509 | push(false); |
twisti@2047 | 510 | break; |
twisti@2047 | 511 | case Bytecodes::_ineg: |
twisti@2047 | 512 | break; |
twisti@2047 | 513 | |
twisti@2047 | 514 | case Bytecodes::_ladd: |
twisti@2047 | 515 | case Bytecodes::_lsub: |
twisti@2047 | 516 | case Bytecodes::_lmul: |
twisti@2047 | 517 | case Bytecodes::_land: |
twisti@2047 | 518 | case Bytecodes::_lxor: |
twisti@2047 | 519 | pop(); |
twisti@2047 | 520 | pop(); |
twisti@2047 | 521 | pop(); |
twisti@2047 | 522 | pop(); |
twisti@2047 | 523 | push(false); |
twisti@2047 | 524 | push(false); |
twisti@2047 | 525 | break; |
twisti@2047 | 526 | case Bytecodes::_lor: |
twisti@2047 | 527 | a = pop(); |
twisti@2047 | 528 | b = pop(); |
twisti@2047 | 529 | push(a && b); |
twisti@2047 | 530 | break; |
twisti@2047 | 531 | case Bytecodes::_ldiv: |
twisti@2047 | 532 | case Bytecodes::_lrem: |
twisti@2047 | 533 | pop(); |
twisti@2047 | 534 | if (!pop()) |
twisti@2047 | 535 | return false; |
twisti@2047 | 536 | pop(); |
twisti@2047 | 537 | pop(); |
twisti@2047 | 538 | push(false); |
twisti@2047 | 539 | push(false); |
twisti@2047 | 540 | break; |
twisti@2047 | 541 | case Bytecodes::_lneg: |
twisti@2047 | 542 | break; |
twisti@2047 | 543 | case Bytecodes::_lshl: |
twisti@2047 | 544 | case Bytecodes::_lshr: |
twisti@2047 | 545 | case Bytecodes::_lushr: |
twisti@2047 | 546 | pop(); |
twisti@2047 | 547 | pop(); |
twisti@2047 | 548 | pop(); |
twisti@2047 | 549 | push(false); |
twisti@2047 | 550 | push(false); |
twisti@2047 | 551 | break; |
twisti@2047 | 552 | |
twisti@2047 | 553 | case Bytecodes::_fadd: |
twisti@2047 | 554 | case Bytecodes::_fsub: |
twisti@2047 | 555 | case Bytecodes::_fmul: |
twisti@2047 | 556 | case Bytecodes::_fdiv: |
twisti@2047 | 557 | case Bytecodes::_frem: |
twisti@2047 | 558 | pop(); |
twisti@2047 | 559 | pop(); |
twisti@2047 | 560 | push(false); |
twisti@2047 | 561 | break; |
twisti@2047 | 562 | case Bytecodes::_fneg: |
twisti@2047 | 563 | break; |
twisti@2047 | 564 | |
twisti@2047 | 565 | case Bytecodes::_dadd: |
twisti@2047 | 566 | case Bytecodes::_dsub: |
twisti@2047 | 567 | case Bytecodes::_dmul: |
twisti@2047 | 568 | case Bytecodes::_ddiv: |
twisti@2047 | 569 | case Bytecodes::_drem: |
twisti@2047 | 570 | pop(); |
twisti@2047 | 571 | pop(); |
twisti@2047 | 572 | pop(); |
twisti@2047 | 573 | pop(); |
twisti@2047 | 574 | push(false); |
twisti@2047 | 575 | push(false); |
twisti@2047 | 576 | break; |
twisti@2047 | 577 | case Bytecodes::_dneg: |
twisti@2047 | 578 | break; |
twisti@2047 | 579 | |
twisti@2047 | 580 | case Bytecodes::_iinc: |
twisti@2047 | 581 | set_local(iter()->get_index(), false); |
twisti@2047 | 582 | break; |
twisti@2047 | 583 | |
twisti@2047 | 584 | case Bytecodes::_lcmp: |
twisti@2047 | 585 | pop(); |
twisti@2047 | 586 | pop(); |
twisti@2047 | 587 | pop(); |
twisti@2047 | 588 | pop(); |
twisti@2047 | 589 | push(false); |
twisti@2047 | 590 | break; |
twisti@2047 | 591 | |
twisti@2047 | 592 | case Bytecodes::_fcmpl: |
twisti@2047 | 593 | case Bytecodes::_fcmpg: |
twisti@2047 | 594 | pop(); |
twisti@2047 | 595 | pop(); |
twisti@2047 | 596 | push(false); |
twisti@2047 | 597 | break; |
twisti@2047 | 598 | |
twisti@2047 | 599 | case Bytecodes::_dcmpl: |
twisti@2047 | 600 | case Bytecodes::_dcmpg: |
twisti@2047 | 601 | pop(); |
twisti@2047 | 602 | pop(); |
twisti@2047 | 603 | pop(); |
twisti@2047 | 604 | pop(); |
twisti@2047 | 605 | push(false); |
twisti@2047 | 606 | break; |
twisti@2047 | 607 | |
twisti@2047 | 608 | case Bytecodes::_i2l: |
twisti@2047 | 609 | push(false); |
twisti@2047 | 610 | break; |
twisti@2047 | 611 | case Bytecodes::_i2f: |
twisti@2047 | 612 | pop(); |
twisti@2047 | 613 | push(false); |
twisti@2047 | 614 | break; |
twisti@2047 | 615 | case Bytecodes::_i2d: |
twisti@2047 | 616 | pop(); |
twisti@2047 | 617 | push(false); |
twisti@2047 | 618 | push(false); |
twisti@2047 | 619 | break; |
twisti@2047 | 620 | |
twisti@2047 | 621 | case Bytecodes::_l2i: |
twisti@2047 | 622 | case Bytecodes::_l2f: |
twisti@2047 | 623 | pop(); |
twisti@2047 | 624 | pop(); |
twisti@2047 | 625 | push(false); |
twisti@2047 | 626 | break; |
twisti@2047 | 627 | case Bytecodes::_l2d: |
twisti@2047 | 628 | pop(); |
twisti@2047 | 629 | pop(); |
twisti@2047 | 630 | push(false); |
twisti@2047 | 631 | push(false); |
twisti@2047 | 632 | break; |
twisti@2047 | 633 | |
twisti@2047 | 634 | case Bytecodes::_f2i: |
twisti@2047 | 635 | pop(); |
twisti@2047 | 636 | push(false); |
twisti@2047 | 637 | break; |
twisti@2047 | 638 | case Bytecodes::_f2l: |
twisti@2047 | 639 | case Bytecodes::_f2d: |
twisti@2047 | 640 | pop(); |
twisti@2047 | 641 | push(false); |
twisti@2047 | 642 | push(false); |
twisti@2047 | 643 | break; |
twisti@2047 | 644 | |
twisti@2047 | 645 | case Bytecodes::_d2i: |
twisti@2047 | 646 | case Bytecodes::_d2f: |
twisti@2047 | 647 | pop(); |
twisti@2047 | 648 | pop(); |
twisti@2047 | 649 | push(false); |
twisti@2047 | 650 | break; |
twisti@2047 | 651 | case Bytecodes::_d2l: |
twisti@2047 | 652 | pop(); |
twisti@2047 | 653 | pop(); |
twisti@2047 | 654 | push(false); |
twisti@2047 | 655 | push(false); |
twisti@2047 | 656 | break; |
twisti@2047 | 657 | |
twisti@2047 | 658 | case Bytecodes::_i2b: |
twisti@2047 | 659 | case Bytecodes::_i2c: |
twisti@2047 | 660 | case Bytecodes::_i2s: |
twisti@2047 | 661 | pop(); |
twisti@2047 | 662 | push(false); |
twisti@2047 | 663 | break; |
twisti@2047 | 664 | |
twisti@2047 | 665 | case Bytecodes::_return: |
twisti@2047 | 666 | case Bytecodes::_ireturn: |
twisti@2047 | 667 | case Bytecodes::_lreturn: |
twisti@2047 | 668 | case Bytecodes::_freturn: |
twisti@2047 | 669 | case Bytecodes::_dreturn: |
twisti@2047 | 670 | case Bytecodes::_areturn: |
twisti@2047 | 671 | break; |
twisti@2047 | 672 | |
twisti@2047 | 673 | default: |
twisti@2047 | 674 | return false; |
twisti@2047 | 675 | } |
twisti@2047 | 676 | } |
twisti@2047 | 677 | |
twisti@2047 | 678 | return true; |
twisti@2047 | 679 | } |
twisti@2047 | 680 | |
twisti@2047 | 681 | void SharkInlinerHelper::initialize_for_check() { |
twisti@2047 | 682 | _locals = NEW_RESOURCE_ARRAY(bool, max_locals()); |
twisti@2047 | 683 | _stack = NEW_RESOURCE_ARRAY(bool, max_stack()); |
twisti@2047 | 684 | |
twisti@2047 | 685 | memset(_locals, 0, max_locals() * sizeof(bool)); |
twisti@2047 | 686 | for (int i = 0; i < target()->arg_size(); i++) { |
twisti@2047 | 687 | SharkValue *arg = entry_state()->stack(target()->arg_size() - 1 - i); |
twisti@2047 | 688 | if (arg && arg->zero_checked()) |
twisti@2047 | 689 | set_local(i, true); |
twisti@2047 | 690 | } |
twisti@2047 | 691 | |
twisti@2047 | 692 | _sp = _stack; |
twisti@2047 | 693 | } |
twisti@2047 | 694 | |
twisti@2047 | 695 | bool SharkInlinerHelper::do_field_access(bool is_get, bool is_field) { |
twisti@2047 | 696 | assert(is_get || is_field, "can't inline putstatic"); |
twisti@2047 | 697 | |
twisti@2047 | 698 | // If the holder isn't linked then there isn't a lot we can do |
twisti@2047 | 699 | if (!target()->holder()->is_linked()) |
twisti@2047 | 700 | return false; |
twisti@2047 | 701 | |
twisti@2047 | 702 | // Get the field |
twisti@2047 | 703 | bool will_link; |
twisti@2047 | 704 | ciField *field = iter()->get_field(will_link); |
twisti@2047 | 705 | if (!will_link) |
twisti@2047 | 706 | return false; |
twisti@2047 | 707 | |
twisti@2047 | 708 | // If the field is mismatched then an exception needs throwing |
twisti@2047 | 709 | if (is_field == field->is_static()) |
twisti@2047 | 710 | return false; |
twisti@2047 | 711 | |
twisti@2047 | 712 | // Pop the value off the stack if necessary |
twisti@2047 | 713 | if (!is_get) { |
twisti@2047 | 714 | pop(); |
twisti@2047 | 715 | if (field->type()->is_two_word()) |
twisti@2047 | 716 | pop(); |
twisti@2047 | 717 | } |
twisti@2047 | 718 | |
twisti@2047 | 719 | // Pop and null-check the receiver if necessary |
twisti@2047 | 720 | if (is_field) { |
twisti@2047 | 721 | if (!pop()) |
twisti@2047 | 722 | return false; |
twisti@2047 | 723 | } |
twisti@2047 | 724 | |
twisti@2047 | 725 | // Push the result if necessary |
twisti@2047 | 726 | if (is_get) { |
twisti@2047 | 727 | bool result_pushed = false; |
twisti@2047 | 728 | if (field->is_constant()) { |
twisti@2047 | 729 | SharkConstant *sc = SharkConstant::for_field(iter()); |
twisti@2047 | 730 | if (sc->is_loaded()) { |
twisti@2047 | 731 | push(sc->is_nonzero()); |
twisti@2047 | 732 | result_pushed = true; |
twisti@2047 | 733 | } |
twisti@2047 | 734 | } |
twisti@2047 | 735 | |
twisti@2047 | 736 | if (!result_pushed) |
twisti@2047 | 737 | push(false); |
twisti@2047 | 738 | |
twisti@2047 | 739 | if (field->type()->is_two_word()) |
twisti@2047 | 740 | push(false); |
twisti@2047 | 741 | } |
twisti@2047 | 742 | |
twisti@2047 | 743 | return true; |
twisti@2047 | 744 | } |
twisti@2047 | 745 | |
twisti@2047 | 746 | bool SharkInliner::attempt_inline(ciMethod *target, SharkState *state) { |
twisti@2047 | 747 | if (SharkIntrinsics::is_intrinsic(target)) { |
twisti@2047 | 748 | SharkIntrinsics::inline_intrinsic(target, state); |
twisti@2047 | 749 | return true; |
twisti@2047 | 750 | } |
twisti@2047 | 751 | |
twisti@2047 | 752 | if (may_be_inlinable(target)) { |
twisti@2047 | 753 | SharkInlinerHelper inliner(target, state); |
twisti@2047 | 754 | if (inliner.is_inlinable()) { |
twisti@2047 | 755 | inliner.do_inline(); |
twisti@2047 | 756 | return true; |
twisti@2047 | 757 | } |
twisti@2047 | 758 | } |
twisti@2047 | 759 | return false; |
twisti@2047 | 760 | } |