370 int idx = (stale >= 0) ? stale : i;
371 ta[idx] = key;
372 return form;
373 }
374 }
375 }
376
377 private LambdaFormBuffer buffer() {
378 return new LambdaFormBuffer(lambdaForm);
379 }
380
381 /// Editing methods for method handles. These need to have fast paths.
382
383 private BoundMethodHandle.SpeciesData oldSpeciesData() {
384 return BoundMethodHandle.speciesData(lambdaForm);
385 }
386 private BoundMethodHandle.SpeciesData newSpeciesData(BasicType type) {
387 return oldSpeciesData().extendWith(type);
388 }
389
390 BoundMethodHandle bindArgumentL(BoundMethodHandle mh, int pos, Object value) {
391 assert(mh.speciesData() == oldSpeciesData());
392 BasicType bt = L_TYPE;
393 MethodType type2 = bindArgumentType(mh, pos, bt);
394 LambdaForm form2 = bindArgumentForm(1+pos);
395 return mh.copyWithExtendL(type2, form2, value);
396 }
397 BoundMethodHandle bindArgumentI(BoundMethodHandle mh, int pos, int value) {
398 assert(mh.speciesData() == oldSpeciesData());
399 BasicType bt = I_TYPE;
400 MethodType type2 = bindArgumentType(mh, pos, bt);
401 LambdaForm form2 = bindArgumentForm(1+pos);
402 return mh.copyWithExtendI(type2, form2, value);
403 }
404
405 BoundMethodHandle bindArgumentJ(BoundMethodHandle mh, int pos, long value) {
406 assert(mh.speciesData() == oldSpeciesData());
407 BasicType bt = J_TYPE;
408 MethodType type2 = bindArgumentType(mh, pos, bt);
409 LambdaForm form2 = bindArgumentForm(1+pos);
430 assert(mh.form.uncustomize() == lambdaForm);
431 assert(mh.form.names[1+pos].type == bt);
432 assert(BasicType.basicType(mh.type().parameterType(pos)) == bt);
433 return mh.type().dropParameterTypes(pos, pos+1);
434 }
435
436 /// Editing methods for lambda forms.
437 // Each editing method can (potentially) cache the edited LF so that it can be reused later.
438
439 LambdaForm bindArgumentForm(int pos) {
440 Transform key = Transform.of(Transform.BIND_ARG, pos);
441 LambdaForm form = getInCache(key);
442 if (form != null) {
443 assert(form.parameterConstraint(0) == newSpeciesData(lambdaForm.parameterType(pos)));
444 return form;
445 }
446 LambdaFormBuffer buf = buffer();
447 buf.startEdit();
448
449 BoundMethodHandle.SpeciesData oldData = oldSpeciesData();
450 BoundMethodHandle.SpeciesData newData = newSpeciesData(lambdaForm.parameterType(pos));
451 Name oldBaseAddress = lambdaForm.parameter(0); // BMH holding the values
452 Name newBaseAddress;
453 NamedFunction getter = newData.getterFunction(oldData.fieldCount());
454
455 if (pos != 0) {
456 // The newly created LF will run with a different BMH.
457 // Switch over any pre-existing BMH field references to the new BMH class.
458 buf.replaceFunctions(oldData.getterFunctions(), newData.getterFunctions(), oldBaseAddress);
459 newBaseAddress = oldBaseAddress.withConstraint(newData);
460 buf.renameParameter(0, newBaseAddress);
461 buf.replaceParameterByNewExpression(pos, new Name(getter, newBaseAddress));
462 } else {
463 // cannot bind the MH arg itself, unless oldData is empty
464 assert(oldData == BoundMethodHandle.SpeciesData.EMPTY);
465 newBaseAddress = new Name(L_TYPE).withConstraint(newData);
466 buf.replaceParameterByNewExpression(0, new Name(getter, newBaseAddress));
467 buf.insertParameter(0, newBaseAddress);
468 }
469
470 form = buf.endEdit();
471 return putInCache(key, form);
472 }
473
474 LambdaForm addArgumentForm(int pos, BasicType type) {
475 Transform key = Transform.of(Transform.ADD_ARG, pos, type.ordinal());
476 LambdaForm form = getInCache(key);
477 if (form != null) {
478 assert(form.arity == lambdaForm.arity+1);
479 assert(form.parameterType(pos) == type);
480 return form;
481 }
|
370 int idx = (stale >= 0) ? stale : i;
371 ta[idx] = key;
372 return form;
373 }
374 }
375 }
376
377 private LambdaFormBuffer buffer() {
378 return new LambdaFormBuffer(lambdaForm);
379 }
380
381 /// Editing methods for method handles. These need to have fast paths.
382
383 private BoundMethodHandle.SpeciesData oldSpeciesData() {
384 return BoundMethodHandle.speciesData(lambdaForm);
385 }
386 private BoundMethodHandle.SpeciesData newSpeciesData(BasicType type) {
387 return oldSpeciesData().extendWith(type);
388 }
389
390 BoundMethodHandle bindArgumentQ(BoundMethodHandle mh, int pos, Object value, MethodHandle unbox) {
391 assert(mh.speciesData() == oldSpeciesData());
392 BasicType bt = Q_TYPE;
393 MethodType type2 = bindArgumentType(mh, pos, bt);
394 LambdaForm form2 = bindArgumentForm(1+pos);
395 return mh.copyWithExtendL(type2, form2, value)
396 .copyWithExtendL(type2, form2, unbox);
397 }
398 BoundMethodHandle bindArgumentL(BoundMethodHandle mh, int pos, Object value) {
399 assert(mh.speciesData() == oldSpeciesData());
400 BasicType bt = L_TYPE;
401 MethodType type2 = bindArgumentType(mh, pos, bt);
402 LambdaForm form2 = bindArgumentForm(1+pos);
403 return mh.copyWithExtendL(type2, form2, value);
404 }
405 BoundMethodHandle bindArgumentI(BoundMethodHandle mh, int pos, int value) {
406 assert(mh.speciesData() == oldSpeciesData());
407 BasicType bt = I_TYPE;
408 MethodType type2 = bindArgumentType(mh, pos, bt);
409 LambdaForm form2 = bindArgumentForm(1+pos);
410 return mh.copyWithExtendI(type2, form2, value);
411 }
412
413 BoundMethodHandle bindArgumentJ(BoundMethodHandle mh, int pos, long value) {
414 assert(mh.speciesData() == oldSpeciesData());
415 BasicType bt = J_TYPE;
416 MethodType type2 = bindArgumentType(mh, pos, bt);
417 LambdaForm form2 = bindArgumentForm(1+pos);
438 assert(mh.form.uncustomize() == lambdaForm);
439 assert(mh.form.names[1+pos].type == bt);
440 assert(BasicType.basicType(mh.type().parameterType(pos)) == bt);
441 return mh.type().dropParameterTypes(pos, pos+1);
442 }
443
444 /// Editing methods for lambda forms.
445 // Each editing method can (potentially) cache the edited LF so that it can be reused later.
446
447 LambdaForm bindArgumentForm(int pos) {
448 Transform key = Transform.of(Transform.BIND_ARG, pos);
449 LambdaForm form = getInCache(key);
450 if (form != null) {
451 assert(form.parameterConstraint(0) == newSpeciesData(lambdaForm.parameterType(pos)));
452 return form;
453 }
454 LambdaFormBuffer buf = buffer();
455 buf.startEdit();
456
457 BoundMethodHandle.SpeciesData oldData = oldSpeciesData();
458 BasicType ptype = lambdaForm.parameterType(pos);
459 BoundMethodHandle.SpeciesData newData = (ptype != Q_TYPE) ? newSpeciesData(ptype)
460 : oldData.extendWith(L_TYPE).extendWith(L_TYPE); // value + unbox MH
461 Name oldBaseAddress = lambdaForm.parameter(0); // BMH holding the values
462 Name newBaseAddress;
463 NamedFunction getter = newData.getterFunction(oldData.fieldCount());
464
465 if (pos != 0) {
466 // The newly created LF will run with a different BMH.
467 // Switch over any pre-existing BMH field references to the new BMH class.
468 buf.replaceFunctions(oldData.getterFunctions(), newData.getterFunctions(), oldBaseAddress);
469 newBaseAddress = oldBaseAddress.withConstraint(newData);
470 buf.renameParameter(0, newBaseAddress);
471 if (ptype == Q_TYPE) {
472 // Q-types are stored in boxed form. Unboxing step is required.
473 int exprPos = lambdaForm.arity();
474 int UNBOX_MH = exprPos++;
475 int BOXED_VALUE = exprPos++;
476 int UNBOXED_VALUE = exprPos++;
477 NamedFunction unboxGetter = newData.getterFunction(oldData.fieldCount()+1);
478 buf.insertExpression(UNBOX_MH, new Name(unboxGetter, newBaseAddress));
479 buf.insertExpression(BOXED_VALUE, new Name(getter, newBaseAddress));
480 MethodType unboxInvokerType = MethodType.methodType(Q_TYPE.basicTypeClass(), L_TYPE.basicTypeClass());
481 Name unbox = new Name(unboxInvokerType, buf.name(UNBOX_MH), buf.name(BOXED_VALUE));
482 buf.insertExpression(UNBOXED_VALUE, unbox);
483 buf.replaceParameterByCopy(pos, UNBOXED_VALUE);
484 } else {
485 buf.replaceParameterByNewExpression(pos, new Name(getter, newBaseAddress));
486 }
487 } else {
488 // cannot bind the MH arg itself, unless oldData is empty
489 assert(oldData == BoundMethodHandle.SpeciesData.EMPTY);
490 newBaseAddress = new Name(L_TYPE).withConstraint(newData);
491 buf.replaceParameterByNewExpression(0, new Name(getter, newBaseAddress));
492 buf.insertParameter(0, newBaseAddress);
493 }
494
495 form = buf.endEdit();
496 return putInCache(key, form);
497 }
498
499 LambdaForm addArgumentForm(int pos, BasicType type) {
500 Transform key = Transform.of(Transform.ADD_ARG, pos, type.ordinal());
501 LambdaForm form = getInCache(key);
502 if (form != null) {
503 assert(form.arity == lambdaForm.arity+1);
504 assert(form.parameterType(pos) == type);
505 return form;
506 }
|