Skip to content

Conversation

@havocp
Copy link

@havocp havocp commented May 2, 2012

No description provided.

havocp added 2 commits May 2, 2012 00:31
These tests currently check that the implicit ExecutionContext
is not used by Future callback methods like onSuccess and map.
 - declare the invariant that all app callbacks have an
   associated ExecutionContext provided at the place
   the callback is passed to a method on Future
 - always run callbacks in their associated EC
 - since all callbacks have their own EC, Promise
   does not need one
 - "internal" callbacks don't need to defer execution either
   since we know the ultimate app callback will do so,
   therefore we can use an immediate executor for these

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see how this will fly. Wasn't your point that you wanted an application executor?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The idea is that modulo bugs, this executor is only used in the lexical scope of the Future class, it's never used for the app's callbacks.

By "app" I just mean "code outside the Future implementation"

Another way to look at it is that if the app has any callbacks on the Future, there is always an app executor "after" this internal one (associated with the app callback). You can see later in the code that in methods that take an implicit executor from the app, that executor is manually used rather than this internal one.

So this internal EC should be an undetectable implementation detail. I tried a different way to do it (adding virtual methods to use rather than the existing onComplete) but I think this way is less code and functionally equivalent.

It also adds the elegance that the patch uses its own new feature (lexically-scoped custom executors) to implement itself - kind of fun!

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we need this executor (see below).

havocp added 2 commits May 4, 2012 11:10
They said the callback ran either immediately or in the
provided ExecutionContext, but really the callback is
guaranteed to be run in the ExecutionContext.
However ExecutionContext.execute() may be run either
immediately or asynchronously from some other ExecutionContext.
Attempt to add some more clarity about why it exists and
why it is safe, for future readers of the code.
@havocp
Copy link
Author

havocp commented May 4, 2012

A couple related follow-on changes are in https://github.com/havocp/scala/commits/havocp-execution-context-2 but I'm not adding them to this pull request (unless you want them here) since they are separable. The follow-on changes add the withDefaultExecutionContext for Java and tweak the _taskStack batching to avoid batching across executors. I'd send a new pull with those follow-on changes if you want them after we sort out this pull.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if one of these throws an exception?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The same thing that happened before, the dispatchFuture/notifyCompleted are still used and still catch exceptions. They are just moved below into bindDispatch(), i.e. the closure that used to be created here is created "in advance" because we need to capture the executor in onComplete rather than capturing it here.

(I reworked this a bit in the follow-on branch I mentioned in comments (not in this pull request yet), the rework may make this clearer but isn't intended to change the behavior. This patch makes the more minimal and straightforward change and avoids the potentially more controversial rework.)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I was thrown off by the fuzziness of "this assumes ..."

@havocp
Copy link
Author

havocp commented May 31, 2012

Hey, thanks for merging! There is still an important bugfix in havocp@1c8fc6d

Should I do a pull vs. phaller/scala or scala/scala for that?

@phaller
Copy link
Owner

phaller commented Jun 6, 2012

Hey Havoc,

No worries- thanks for your pull request. It spawned a lot of useful discussion and we have high hopes for the changes.

Concerning the bugfix: could you please submit a pull vs. scala/scala master? Also, it would be best if you would put in a "review by @axel22", just because I'm off the grid for a few days.

Thanks!

On Jun 1, 2012, at 12:25 AM, Havoc Pennington wrote:

Hey, thanks for merging! There is still an important bugfix in havocp@1c8fc6d

Should I do a pull vs. phaller/scala or scala/scala for that?


Reply to this email directly or view it on GitHub:
#16 (comment)

@axel22
Copy link
Collaborator

axel22 commented Jun 6, 2012

Yep, I'll review this.

phaller pushed a commit that referenced this pull request Nov 14, 2014
In Scala 2.8.2, an optimization was added to create a static
cache for Symbol literals (ie, the results of `Symbol.apply("foo"))`.
This saves the map lookup on the second pass through code.

This actually was broken somewhere during the Scala 2.10 series,
after the addition of an overloaded `apply` method to `Symbol`.

The cache synthesis code was made aware of the overload and brought
back to working condition recently, in scala#3149.

However, this has uncovered a latent bug when the Symbol literals are
defined with traits.

One of the enclosed tests failed with:

	  jvm > t8933b-run.log
	java.lang.IllegalAccessError: tried to access field MotherClass.symbol$1 from class MixinWithSymbol$class
	        at MixinWithSymbol$class.symbolFromTrait(A.scala:3)
	        at MotherClass.symbolFromTrait(Test.scala:1)

This commit simply disables the optimization if we are in a trait.
Alternative fixes might be: a) make the static Symbol cache field
public / b) "mixin" the static symbol cache. Neither of these
seem worth the effort and risk for an already fairly situational
optimization.

Here's how the optimization looks in a class:

	% cat sandbox/test.scala; qscalac sandbox/test.scala && echo ":javap C" | qscala;
	class C {
	  'a; 'b
	}
	Welcome to Scala version 2.11.5-20141106-145558-aa558dce6d (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_20).
	Type in expressions to have them evaluated.
	Type :help for more information.

	scala> :javap C
	  Size 722 bytes
	  MD5 checksum 6bb00189166917254e8d40499ee7c887
	  Compiled from "test.scala"
	public class C

	{
	  public static {};
	    descriptor: ()V
	    flags: ACC_PUBLIC, ACC_STATIC
	    Code:
	      stack=2, locals=0, args_size=0
	         0: getstatic     #16                 // Field scala/Symbol$.MODULE$:Lscala/Symbol$;
	         3: ldc           scala#18                 // String a
	         5: invokevirtual scala#22                 // Method scala/Symbol$.apply:(Ljava/lang/String;)Lscala/Symbol;
	         8: putstatic     scala#26                 // Field symbol$1:Lscala/Symbol;
	        11: getstatic     #16                 // Field scala/Symbol$.MODULE$:Lscala/Symbol$;
	        14: ldc           scala#28                 // String b
	        16: invokevirtual scala#22                 // Method scala/Symbol$.apply:(Ljava/lang/String;)Lscala/Symbol;
	        19: putstatic     scala#31                 // Field symbol$2:Lscala/Symbol;
	        22: return

	  public C();
	    descriptor: ()V
	    flags: ACC_PUBLIC
	    Code:
	      stack=1, locals=1, args_size=1
	         0: aload_0
	         1: invokespecial scala#34                 // Method java/lang/Object."<init>":()V
	         4: getstatic     scala#26                 // Field symbol$1:Lscala/Symbol;
	         7: pop
	         8: getstatic     scala#31                 // Field symbol$2:Lscala/Symbol;
	        11: pop
	        12: return
	}

fixup
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants