Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/builtins/builtins-utils.h" | 5 #include "src/builtins/builtins-utils.h" |
| 6 #include "src/builtins/builtins.h" | 6 #include "src/builtins/builtins.h" |
| 7 | 7 |
| 8 #include "src/code-factory.h" | |
| 8 #include "src/promise-utils.h" | 9 #include "src/promise-utils.h" |
| 9 | 10 |
| 10 namespace v8 { | 11 namespace v8 { |
| 11 namespace internal { | 12 namespace internal { |
| 12 | 13 |
| 13 // ES#sec-promise-resolve-functions | 14 // ES#sec-promise-resolve-functions |
| 14 // Promise Resolve Functions | 15 // Promise Resolve Functions |
| 15 BUILTIN(PromiseResolveClosure) { | 16 BUILTIN(PromiseResolveClosure) { |
| 16 HandleScope scope(isolate); | 17 HandleScope scope(isolate); |
| 17 | 18 |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 73 &resolve, &reject); | 74 &resolve, &reject); |
| 74 | 75 |
| 75 Handle<FixedArray> result = isolate->factory()->NewFixedArray(2); | 76 Handle<FixedArray> result = isolate->factory()->NewFixedArray(2); |
| 76 result->set(0, *resolve); | 77 result->set(0, *resolve); |
| 77 result->set(1, *reject); | 78 result->set(1, *reject); |
| 78 | 79 |
| 79 return *isolate->factory()->NewJSArrayWithElements(result, FAST_ELEMENTS, 2, | 80 return *isolate->factory()->NewJSArrayWithElements(result, FAST_ELEMENTS, 2, |
| 80 NOT_TENURED); | 81 NOT_TENURED); |
| 81 } | 82 } |
| 82 | 83 |
| 84 void Builtins::Generate_PromiseConstructor( | |
| 85 compiler::CodeAssemblerState* state) { | |
| 86 CodeStubAssembler a(state); | |
| 87 typedef CodeStubAssembler::Variable Variable; | |
| 88 typedef CodeStubAssembler::Label Label; | |
| 89 typedef compiler::Node Node; | |
| 90 | |
| 91 Node* const executor = a.Parameter(1); | |
| 92 Node* const new_target = a.Parameter(2); | |
| 93 Node* const context = a.Parameter(4); | |
| 94 Isolate* isolate = a.isolate(); | |
| 95 | |
| 96 Label if_targetisundefined(&a, Label::kDeferred); | |
| 97 | |
| 98 a.GotoIf(a.WordEqual(new_target, a.UndefinedConstant()), | |
| 99 &if_targetisundefined); | |
| 100 | |
| 101 Label if_notcallable(&a, Label::kDeferred), | |
| 102 if_rejectpromise(&a, Label::kDeferred); | |
|
jgruber
2016/11/22 08:55:55
if_rejectpromise could be moved into the run_execu
gsathya
2016/11/23 14:31:18
Done.
| |
| 103 | |
| 104 a.GotoIf(a.TaggedIsSmi(executor), &if_notcallable); | |
| 105 | |
| 106 Node* const executor_map = a.LoadMap(executor); | |
| 107 a.GotoUnless(a.IsCallableMap(executor_map), &if_notcallable); | |
| 108 | |
| 109 Node* const native_context = a.LoadNativeContext(context); | |
| 110 Node* const promise_fun = | |
| 111 a.LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX); | |
| 112 | |
| 113 Label if_targetisnotmodified(&a), if_targetismodified(&a, Label::kDeferred), | |
| 114 run_executor(&a), out(&a), debug_push(&a, Label::kDeferred), | |
| 115 debug_pop(&a, Label::kDeferred); | |
| 116 a.Branch(a.WordEqual(promise_fun, new_target), &if_targetisnotmodified, | |
| 117 &if_targetismodified); | |
| 118 | |
| 119 Variable var_result(&a, MachineRepresentation::kTagged), | |
| 120 var_reject_call(&a, MachineRepresentation::kTagged), | |
| 121 var_reason(&a, MachineRepresentation::kTagged); | |
| 122 | |
| 123 a.Bind(&if_targetisnotmodified); | |
| 124 { | |
| 125 Node* const initial_map = a.LoadObjectField( | |
| 126 promise_fun, JSFunction::kPrototypeOrInitialMapOffset); | |
| 127 | |
| 128 Node* const instance = a.AllocateJSObjectFromMap(initial_map); | |
| 129 var_result.Bind(instance); | |
| 130 a.Branch(a.IsDebugActive(), &debug_push, &run_executor); | |
| 131 } | |
| 132 | |
| 133 a.Bind(&if_targetismodified); | |
| 134 { | |
| 135 Node* const instance = | |
| 136 a.CallRuntime(Runtime::kNewObject, context, promise_fun, new_target); | |
|
jgruber
2016/11/22 08:55:55
Just curious, why is it not possible to call a.All
gsathya
2016/11/23 14:31:18
The subclass setup seemed more involved and I wasn
| |
| 137 | |
| 138 var_result.Bind(instance); | |
| 139 a.Branch(a.IsDebugActive(), &debug_push, &run_executor); | |
| 140 } | |
| 141 | |
| 142 a.Bind(&debug_push); | |
| 143 { | |
| 144 a.CallRuntime(Runtime::kDebugPushPromise, context, var_result.value()); | |
| 145 a.Goto(&run_executor); | |
| 146 } | |
| 147 | |
| 148 a.Bind(&run_executor); | |
| 149 { | |
| 150 Node* const key = | |
| 151 a.HeapConstant(a.isolate()->factory()->promise_state_symbol()); | |
| 152 Node* const value = a.SmiConstant(Smi::FromInt(kPromisePending)); | |
| 153 Node* const language_mode = a.SmiConstant(Smi::FromInt(STRICT)); | |
| 154 a.CallRuntime(Runtime::kSetProperty, context, var_result.value(), key, | |
| 155 value, language_mode); | |
| 156 Node* const resolving_functions = a.CallRuntime( | |
| 157 Runtime::kCreateResolvingFunctions, context, var_result.value()); | |
| 158 Node* const resolve = | |
| 159 a.LoadFixedArrayElement(resolving_functions, a.IntPtrConstant(0)); | |
| 160 Node* const reject = | |
| 161 a.LoadFixedArrayElement(resolving_functions, a.IntPtrConstant(1)); | |
| 162 var_reject_call.Bind(reject); | |
|
jgruber
2016/11/22 08:55:55
Seems like you can just use the Node* reject varia
gsathya
2016/11/23 14:31:18
Done.
| |
| 163 Callable call_callable = CodeFactory::Call(isolate); | |
| 164 | |
| 165 Node* const maybe_exception = | |
| 166 a.CallJS(call_callable, context, executor, a.UndefinedConstant(), | |
| 167 resolve, reject); | |
| 168 | |
| 169 a.GotoIfException(maybe_exception, &if_rejectpromise, &var_reason); | |
| 170 a.Branch(a.IsDebugActive(), &debug_pop, &out); | |
| 171 } | |
| 172 | |
| 173 a.Bind(&if_rejectpromise); | |
| 174 { | |
| 175 Callable call_callable = CodeFactory::Call(isolate); | |
| 176 a.CallJS(call_callable, context, var_reject_call.value(), | |
| 177 a.UndefinedConstant(), var_reason.value()); | |
| 178 a.Branch(a.IsDebugActive(), &debug_pop, &out); | |
| 179 } | |
| 180 | |
| 181 a.Bind(&debug_pop); | |
| 182 { | |
| 183 a.CallRuntime(Runtime::kDebugPopPromise, context); | |
| 184 a.Goto(&out); | |
| 185 } | |
| 186 | |
| 187 a.Bind(&out); | |
| 188 a.Return(var_result.value()); | |
| 189 | |
| 190 // 1. If NewTarget is undefined, throw a TypeError exception. | |
| 191 a.Bind(&if_targetisundefined); | |
| 192 { | |
| 193 Node* const message_id = | |
| 194 a.SmiConstant(Smi::FromInt(MessageTemplate::kNotAPromise)); | |
|
jgruber
2016/11/22 08:55:55
Here and elsewhere: since recently you can just ca
gsathya
2016/11/23 14:31:18
Done.
| |
| 195 a.CallRuntime(Runtime::kThrowTypeError, context, message_id, new_target); | |
| 196 // a.ToString(a, new_target)); | |
|
jgruber
2016/11/22 08:55:55
Please remove comment.
gsathya
2016/11/23 14:31:18
Done.
| |
| 197 a.Return(a.UndefinedConstant()); // Never reached. | |
| 198 } | |
| 199 | |
| 200 // 2. If IsCallable(executor) is false, throw a TypeError exception. | |
| 201 a.Bind(&if_notcallable); | |
| 202 { | |
| 203 Node* const message_id = | |
| 204 a.SmiConstant(Smi::FromInt(MessageTemplate::kResolverNotAFunction)); | |
| 205 a.CallRuntime(Runtime::kThrowTypeError, context, message_id, executor); | |
| 206 a.Return(a.UndefinedConstant()); // Never reached. | |
| 207 } | |
| 208 } | |
| 209 | |
| 210 void Builtins::Generate_PromiseInternalConstructor( | |
| 211 compiler::CodeAssemblerState* state) { | |
| 212 typedef compiler::Node Node; | |
| 213 CodeStubAssembler a(state); | |
| 214 | |
| 215 Node* const context = a.Parameter(3); | |
| 216 Node* const native_context = a.LoadNativeContext(context); | |
| 217 Node* const promise_fun = | |
| 218 a.LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX); | |
| 219 Node* const initial_map = | |
| 220 a.LoadObjectField(promise_fun, JSFunction::kPrototypeOrInitialMapOffset); | |
| 221 Node* const instance = a.AllocateJSObjectFromMap(initial_map); | |
| 222 a.Return(instance); | |
| 223 } | |
| 224 | |
| 225 // TODO(gsathya): Refactor promise.js::IsPromise to use this. | |
| 226 void Builtins::Generate_IsPromise(compiler::CodeAssemblerState* state) { | |
| 227 CodeStubAssembler a(state); | |
| 228 typedef compiler::Node Node; | |
| 229 typedef CodeStubAssembler::Label Label; | |
| 230 | |
| 231 Node* const maybe_promise = a.Parameter(1); | |
| 232 Label if_ispromise(&a), if_isnotpromise(&a, Label::kDeferred); | |
| 233 a.GotoIf(a.TaggedIsSmi(maybe_promise), &if_isnotpromise); | |
| 234 | |
| 235 Node* const maybe_promise_type = | |
| 236 a.LoadMapInstanceType(a.LoadMap(maybe_promise)); | |
| 237 | |
| 238 a.Branch(a.Word32Equal(maybe_promise_type, a.Int32Constant(JS_PROMISE_TYPE)), | |
| 239 &if_ispromise, &if_isnotpromise); | |
| 240 | |
| 241 a.Bind(&if_ispromise); | |
| 242 a.Return(a.BooleanConstant(true)); | |
| 243 | |
| 244 a.Bind(&if_isnotpromise); | |
| 245 a.Return(a.BooleanConstant(false)); | |
| 246 } | |
| 247 | |
| 83 } // namespace internal | 248 } // namespace internal |
| 84 } // namespace v8 | 249 } // namespace v8 |
| OLD | NEW |