Chromium Code Reviews| Index: src/builtins/builtins-promise.cc |
| diff --git a/src/builtins/builtins-promise.cc b/src/builtins/builtins-promise.cc |
| index 345625d6d098d09eeb7686658803da7bdbcfa046..351cbfe5cc7d72e1c2dfc2a40ec7056589c0b79b 100644 |
| --- a/src/builtins/builtins-promise.cc |
| +++ b/src/builtins/builtins-promise.cc |
| @@ -904,6 +904,50 @@ void PromiseBuiltinsAssembler::PromiseFulfill( |
| } |
| } |
| +void PromiseBuiltinsAssembler::BranchIfAccessCheckFailed( |
| + Node* context, Node* promise_constructor, Node* executor, |
| + Label* if_noaccess) { |
| + Variable var_executor(this, MachineRepresentation::kTagged); |
| + var_executor.Bind(executor); |
| + Label has_access(this), call_runtime(this, Label::kDeferred); |
| + |
| + // If executor is a bound function, load the bound function until we've |
| + // reached an actual function. |
| + Label found_function(this), loop_over_bound_function(this, &var_executor); |
| + Goto(&loop_over_bound_function); |
| + Bind(&loop_over_bound_function); |
|
gsathya
2017/01/11 17:27:31
i wonder if its better to duplicate the IsJSFuncti
jochen (gone - plz use gerrit)
2017/01/11 18:09:57
afaik that shouldn't make that much of a differenc
Igor Sheludko
2017/01/12 08:31:11
I think it's fine to avoid marking the block as de
|
| + { |
| + GotoIf(IsJSFunction(var_executor.value()), &found_function); |
| + GotoUnless(IsJSBoundFunction(var_executor.value()), &call_runtime); |
|
Igor Sheludko
2017/01/12 08:31:11
Here you are loading map and then instance type se
|
| + var_executor.Bind(LoadObjectField( |
| + var_executor.value(), JSBoundFunction::kBoundTargetFunctionOffset)); |
| + Goto(&loop_over_bound_function); |
| + } |
| + |
| + // Load the context from the function and compare it to the Promise |
| + // constructor's context. If they match, everything is fine, otherwise, bail |
| + // out to the runtime. |
| + Bind(&found_function); |
| + { |
| + Node* native_context = LoadNativeContext(context); |
|
gsathya
2017/01/11 17:27:31
this can be an argument to this function, no need
jochen (gone - plz use gerrit)
2017/01/11 18:09:57
done
|
| + Node* function_context = |
| + LoadObjectField(var_executor.value(), JSFunction::kContextOffset); |
| + Node* native_function_context = LoadNativeContext(function_context); |
| + Branch(WordEqual(native_context, native_function_context), &has_access, |
| + &call_runtime); |
| + } |
| + |
| + Bind(&call_runtime); |
| + { |
| + Branch(WordEqual(CallRuntime(Runtime::kAllowDynamicFunction, context, |
| + promise_constructor), |
| + BooleanConstant(true)), |
| + &has_access, if_noaccess); |
| + } |
| + |
| + Bind(&has_access); |
| +} |
| + |
| // ES#sec-promise-reject-functions |
| // Promise Reject Functions |
| TF_BUILTIN(PromiseRejectClosure, PromiseBuiltinsAssembler) { |
| @@ -961,7 +1005,9 @@ TF_BUILTIN(PromiseConstructor, PromiseBuiltinsAssembler) { |
| Node* const is_debug_active = IsDebugActive(); |
| Label if_targetisnotmodified(this), |
| if_targetismodified(this, Label::kDeferred), run_executor(this), |
| - debug_push(this); |
| + debug_push(this), if_noaccess(this, Label::kDeferred); |
| + |
| + BranchIfAccessCheckFailed(context, promise_fun, executor, &if_noaccess); |
| Branch(WordEqual(promise_fun, new_target), &if_targetisnotmodified, |
| &if_targetismodified); |
| @@ -1046,6 +1092,15 @@ TF_BUILTIN(PromiseConstructor, PromiseBuiltinsAssembler) { |
| CallRuntime(Runtime::kThrowTypeError, context, message_id, executor); |
| Return(UndefinedConstant()); // Never reached. |
| } |
| + |
| + // Silently fail if the stack looks fishy. |
| + Bind(&if_noaccess); |
| + { |
| + Node* const counter_id = |
| + SmiConstant(v8::Isolate::kPromiseConstructorReturnedUndefined); |
| + CallRuntime(Runtime::kCountUsage, context, counter_id); |
| + Return(UndefinedConstant()); |
| + } |
| } |
| TF_BUILTIN(PromiseInternalConstructor, PromiseBuiltinsAssembler) { |