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